* Re: [PATCH 0/3] clk: Add __clk_disable_unprepare_counts_only() and use this in simple[fb|drm]
From: Hans de Goede @ 2026-06-24 9:06 UTC (permalink / raw)
To: Maxime Ripard
Cc: Brian Masney, Michael Turquette, Stephen Boyd, Thomas Zimmermann,
Javier Martinez Canillas, Maarten Lankhorst, Helge Deller,
Bjorn Andersson, Konrad Dybcio, Dmitry Baryshkov, Rob Clark,
linux-clk, dri-devel, ~postmarketos/upstreaming
In-Reply-To: <20260624-ultramarine-beetle-of-vastness-acd51e@houat>
Hi,
On 24-Jun-26 10:53, Maxime Ripard wrote:
> On Thu, May 28, 2026 at 03:02:09PM +0200, Hans de Goede wrote:
>> On 28-May-26 2:08 PM, Maxime Ripard wrote:
>>> On Thu, May 28, 2026 at 12:12:10PM +0200, Hans de Goede wrote:
>>>> Hi Brian,
>>>>
>>>> On 28-May-26 1:03 AM, Brian Masney wrote:
>>>>> Hi Hans,
>>>>>
>>>>> On Wed, May 27, 2026 at 11:48:08AM +0200, Hans de Goede wrote:
>>>>>> 2) One option considered was detaching the simple-framebuffer driver later,
>>>>>> after the real display driver has had a chance to claim the clocks. But
>>>>>> this won't work in cases where the real display driver picks different
>>>>>> parent clocks then the boot firmware did and needs to reparent clocks.
>>>>>
>>>>> Why won't that work in the case where different parent clocks are selected?
>>>>> I'll describe a scenario below.
>>>>>
>>>>>>
>>>>>> Basically the goal is for things to behave as if the simple-framebuffer
>>>>>> driver was not there at all, because that leaves the hw in the state
>>>>>> the real display driver expects.
>>>>>
>>>>> I think the deferred unbinding could have some potential here where
>>>>> there is some kind of notification mechanism between simple-framebuffer
>>>>> and the real drm driver. So:
>>>>>
>>>>> - simple-framebuffer driver takes reference(s) to the clk(s).
>>>>>
>>>>> - real drm driver eventually loads, takes reference(s) to the necessary
>>>>> clk(s).
>>>>>
>>>>> - real drm driver sends a notification to simple-framebuffer that it's
>>>>> done, and has control.
>>>>>
>>>>> - simple-framebuffer can unbind and release its references to the clks.
>>>>>
>>>>> No clks will be shutdown prematurely in this scenario.
>>>>>
>>>>> If the real drm driver needs a different parent, then presumably things
>>>>> should be setup correctly, and simple-framebuffer can have the clocks
>>>>> shut down when it calls clk_disable_unprepare().
>>>>
>>>> If the real drm driver needs a different parent, then how does it
>>>> do the reparenting while the simple-framebuffer driver is holding
>>>> a reference to the clock ? In that case the clock might have
>>>> a protected_count of non 0 (depends on the core-clk flags) and
>>>> reparenting won't work.
>>>
>>> The only case where it should reparent you listed was that you might
>>> need to pick up a different resolution. However, that can only be
>>> enforced by an ioctl or a client.
>>>
>>> simplefb/drm is removed in msm_drm_kms_init. The device is published
>>> drm_dev_register called right after msm_drm_kms_init, and the clients
>>> are registered in msm_drm_kms_post_init, called after drm_dev_register.
>>>
>>> There's no way in the current msm architecture to have a modeset happen
>>> while the simpledrm driver is still active.
>>
>> Ok, new plan, please let me know what you think about this:
>>
>> 1. Add a new "disable" callback argument to
>> devm_aperture_acquire_for_platform_device() and store this in
>> struct aperture_range
>>
>> 2. Add a new aperture_disable_conflicting_devices() which
>> calls the disable callback for matching devices.
>>
>> 3. Have the simple[fd|drm] drivers implement a disable callback
>> which unregisters the drm dev and releases any claims on the
>> aperture mem-region, while keeping clks, regulators, etc.
>> enabled. And have them check if disable was called on remove()
>> and if not do the disable() things on remove(0
>>
>> 4. Have msm call aperture_disable_conflicting_devices() where it
>> now call aperture_remove_conflicting_devices() and call
>> aperture_remove_conflicting_devices() at the point where it has
>> claimed any clks it needs.
>>
>> Does this sound like something which would be acceptable ?
>
> Generally speaking, yes, but I'd also like to understand what you're
> trying to fix exactly, because I don't see how it can be what you hinted
> at before.
The basic problem is that on handover from simpledrm -> msm
the clocks get turned off, without fully shutting down the
display pipeline first (since simpledrm does not know how).
Then when msm later tries to re-enable things, the hw is
in a confused state and we hit this error:
[ 2.980181] disp_cc_mdss_dptx3_pixel0_clk_src: rcg didn't update its configuration.
[ 2.980272] WARNING: drivers/clk/qcom/clk-rcg2.c:136 at update_config+0xdc/0x100
So we need a way to handover things to the msm driver
without anything getting disabled by simpledrm in an
uncontrolled (not following proper pwr-down seq) manner.
The idea behind the 2 step simpledrm removal process is
that on the first step drm_dev_unplug() gets called for
the simpledrm device and any struct resource claim on
the aperture gets released. While keeping all the clocks,
regulators, etc. claims.
Then msm can take things over and call the second step
when it has taken everything over. On the second step
simpeldrm will release its enable count ref on the clocks,
etc. in question.
In the mean time I've actually already prototyped this, see:
https://github.com/jwrdegoede/linux-sunxi/commits/main
Note this is my main wip branch with all kinda stuff
in there and this gets forced pushes regularly.
Regards,
Hans
p.s.
I've not posted this upstream yet because unlike
the __clk_disable_unprepare_counts_only() approach this
does not work atm, because it seems the msm driver only
claims some DP related clocks on the first modeset
from userspace rather then during probe().
This msm issue is something which we need to fix regardless,
also for when the clock framework gets moved to using
sync-state handling for turning off unused clocks, since
any clocks consumed by the msm dt-node will then also get
turned off directly after probe().
^ permalink raw reply
* [meta-lts-collab][kirkstone][PATCH] openssl: upgrade 3.0.20 -> 3.0.21
From: Aditya GS @ 2026-06-24 6:26 UTC (permalink / raw)
To: yocto-patches; +Cc: Aditya GS, Aditya GS
Upgrade OpenSSL from 3.0.20 to 3.0.21.
This upgrade brings in upstream fixes for multiple CVEs:
- CVE-2026-45447 (High): heap use-after-free in PKCS7_verify()
- CVE-2026-7383: heap buffer overflow in ASN.1 multibyte string
- CVE-2026-9076: out-of-bounds read in CMS password-based decryption
- CVE-2026-34180: heap buffer over-read in ASN.1 content parsing
- CVE-2026-42764: NULL pointer dereference in QUIC server packet handling
- CVE-2026-45445: AES-OCB IV ignored on EVP_Cipher() path
- CVE-2026-34182: CMS AuthEnvelopedData may accept forged messages
- CVE-2026-42766: NULL pointer dereference in password-based CMS decryption
- CVE-2026-42770: FFC-DH peer validation uses attacker-supplied q
- CVE-2026-45446: incorrect tag processing for empty messages in AES-GCM-SIV and AES-SIV modes
As a result of this upgrade, the following CVEs are already fixed in the
upstream version and no longer require local patches:
- CVE-2024-41996: vulnerability that could lead to denial of service
- CVE-2023-50781: fixes related to certificate validation and memory handling
Upstream changelog:
https://github.com/openssl/openssl/blob/openssl-3.0.21/NEWS.md
Signed-off-by: Aditya GS <adityags2004@gmail.com>
Signed-off-by: Aditya GS <aditya.gs@bmwtechworks.in>
---
.../openssl/{openssl_3.0.20.bb => openssl_3.0.21.bb} | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
rename meta-core/recipes-connectivity/openssl/{openssl_3.0.20.bb => openssl_3.0.21.bb} (96%)
diff --git a/meta-core/recipes-connectivity/openssl/openssl_3.0.20.bb b/meta-core/recipes-connectivity/openssl/openssl_3.0.21.bb
similarity index 96%
rename from meta-core/recipes-connectivity/openssl/openssl_3.0.20.bb
rename to meta-core/recipes-connectivity/openssl/openssl_3.0.21.bb
index d33874e..fffe303 100644
--- a/meta-core/recipes-connectivity/openssl/openssl_3.0.20.bb
+++ b/meta-core/recipes-connectivity/openssl/openssl_3.0.21.bb
@@ -12,20 +12,13 @@ SRC_URI = "https://github.com/openssl/openssl/releases/download/openssl-${PV}/op
file://0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch \
file://afalg.patch \
file://0001-Configure-do-not-tweak-mips-cflags.patch \
- file://CVE-2024-41996.patch \
- file://CVE-2023-50781-1.patch \
- file://CVE-2023-50781-2.patch \
- file://CVE-2023-50781-3.patch \
- file://CVE-2023-50781-4.patch \
- file://CVE-2023-50781-5.patch \
- file://CVE-2023-50781-6.patch \
"
SRC_URI:append:class-nativesdk = " \
file://environment.d-openssl.sh \
"
-SRC_URI[sha256sum] = "c80a01dfc70ece4dc21168932c37739042d404d46ccc81a5986dd75314ecda6f"
+SRC_URI[sha256sum] = "617e29af8e421f46649484a4937e48c685e47f46488167c982f88bc4ec1d522f"
inherit lib_package multilib_header multilib_script ptest perlnative
MULTILIB_SCRIPTS = "${PN}-bin:${bindir}/c_rehash"
--
2.34.1
^ permalink raw reply related
* Re: [Intel-wired-lan] [PATCH net] igc: Fix RX HW timestamp reporting when NET_RX_BUSY_POLL is disabled
From: Florian Bezdeka @ 2026-06-24 9:05 UTC (permalink / raw)
To: Kwapulinski, Piotr, Ding Meng, Nguyen, Anthony L,
Kitszel, Przemyslaw, andrew+netdev@lunn.ch, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
Kiszka, Jan
Cc: intel-wired-lan@lists.osuosl.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, wq.wang@siemens.com
In-Reply-To: <BL1PR11MB59796B99C5A7709B07000D68F3EE2@BL1PR11MB5979.namprd11.prod.outlook.com>
On Tue, 2026-06-23 at 09:46 +0000, Kwapulinski, Piotr wrote:
> > -----Original Message-----
> > From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Ding Meng via Intel-wired-lan
> > Sent: Monday, June 22, 2026 6:13 AM
> > To: Nguyen, Anthony L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; andrew+netdev@lunn.ch; davem@davemloft.net; edumazet@google.com; kuba@kernel.org; pabeni@redhat.com; Kiszka, Jan <jan.kiszka@siemens.com>; Bezdeka, Florian <florian.bezdeka@siemens.com>
> > Cc: intel-wired-lan@lists.osuosl.org; linux-kernel@vger.kernel.org; netdev@vger.kernel.org; meng.ding@siemens.com; wq.wang@siemens.com
> > Subject: [Intel-wired-lan] [PATCH net] igc: Fix RX HW timestamp reporting when NET_RX_BUSY_POLL is disabled
> >
> > When CONFIG_NET_RX_BUSY_POLL is deactivated, fetching RX HW timestamps from the NIC no longer works as expected.
> >
> > This occurs because disabling CONFIG_NET_RX_BUSY_POLL disables the SKB NAPI mapping in __skb_mark_napi_id(). Consequently, get_timestamp() fails to perform its driver lookup, and the igc driver's struct net_device_ops::ndo_get_tstamp is never invoked.
> >
> > Instead, get_timestamp() falls back to use shhwtstamps(skb)->hwtstamp, a field that the driver has not populated.
> >
> > Fix this by populating the hwtstamp field with the correct timestamp in the default timer when CONFIG_NET_RX_BUSY_POLL is disabled.
> >
> > Fixes: 069b142f5819 ("igc: Add support for PTP .getcyclesx64()")
> > Co-developed-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > Signed-off-by: Ding Meng <meng.ding@siemens.com>
> > ---
> > drivers/net/ethernet/intel/igc/igc_main.c | 38 ++++++++++++++++-------
> > 1 file changed, 26 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
> > index 8ac16808023..1da8d7aa76d 100644
> > --- a/drivers/net/ethernet/intel/igc/igc_main.c
> > +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> > @@ -1992,7 +1992,26 @@ static struct sk_buff *igc_build_skb(struct igc_ring *rx_ring,
> > return skb;
> > }
> >
> > -static struct sk_buff *igc_construct_skb(struct igc_ring *rx_ring,
> > +static void igc_construct_skb_timestamps(struct igc_adapter *adapter,
> > + struct sk_buff *skb,
> > + struct igc_xdp_buff *ctx)
> > +{
> > + if (!ctx->rx_ts)
> > + return;
> > +#ifdef CONFIG_NET_RX_BUSY_POLL
> > + skb_shinfo(skb)->tx_flags |= SKBTX_HW_TSTAMP_NETDEV;
> > + skb_hwtstamps(skb)->netdev_data = ctx->rx_ts; #else
> > + struct igc_inline_rx_tstamps *tstamps;
> Please move at the top of the function and add:
That would trigger a "unused variable" warning in the
CONFIG_NET_RX_BUSY_POLL case.
Btw: I was really confused that the #else statement moved to the end of
the previous line. Might someone be using a wrongly configured mail
client here?
Florian
> Reviewed-by: Piotr Kwapulinski <piotr.kwapulinski@intel.com
>
> > +
> > + tstamps = ctx->rx_ts;
> > + skb_hwtstamps(skb)->hwtstamp = igc_ptp_rx_pktstamp(adapter,
> > + tstamps->timer0);
> > +#endif
> > +}
> > +
[snip]
^ permalink raw reply
* RE: [PATCH v2 1/3] xen/device-tree: Parse 'cpu-map' node for CPU topology exploration
From: Hirokazu Takahashi @ 2026-06-24 9:05 UTC (permalink / raw)
To: Jan Beulich
Cc: Mykyta_Poturai@epam.com, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Roger Pau Monné,
xen-devel@lists.xenproject.org
In-Reply-To: <0c37c031-cc21-44d2-9ef6-4baf6f24d74b@suse.com>
Hello,
> > --- /dev/null
> > +++ b/xen/common/cpu-topology.c
> > @@ -0,0 +1,30 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +
> > +#include <xen/cpumask.h>
> > +#include <xen/cpu-topology.h>
> > +#include <xen/init.h>
> > +#include <xen/acpi.h>
> > +
> > +void __init init_cpu_topology(void)
> > +{
> > + const unsigned int nr_cpus = cpumask_last(&cpu_possible_map) +
> 1U;
> > +
> > + cpu_topology = xzalloc_array(struct cpu_topology, nr_cpus);
>
> cpu_topology exists as a global variable only when DT is in use. I think the
> definition needs to move here (from common/device-tree/cpu-topology.c).
Okay
> As to the size of the array, it's not quite clear to me whether by doing it
> this way (instead of using nr_cpu_ids) we're not setting ourselves up for
> trouble.
On ARM64 Xen, nr_cpu_ids represents the total number of populated/available
CPUs, but unfortunately it cannot be relied upon as the maximum CPU ID.
For instance, if a CPU node in the Device Tree has an invalid 'enable-method'
property, that CPU ID slot is still consumed during the initial parsing, but
the CPU is not counted towards nr_cpu_ids. This can result in a sparse CPU ID
allocation where the maximum CPU ID actually exceeds.
If we were to use nr_cpu_ids as the array size here, we would risk an
out-of-bounds access under such faulty Device Tree configurations. This is
why I used "cpumask_last(&cpu_possible_map) + 1U" to ensure the array is
large enough to cover the highest allocated CPU ID.
Consequently, there might actually be potential bugs in other parts of Xen
where nr_cpu_ids is incorrectly assumed to be the upper bound for CPU ID
indexing on ARM.
> > + if ( !cpu_topology )
> > + panic("Failed to allocate memory for cpu_topology array\n");
>
> I question such uses of panic(): Surely we can do without any NUMA info,
> it's only performance which is going to suffer.
Okay, I will replace the panic() with a XENLOG_WARNING printk.
> > +
> > +static struct dt_device_node * __init dt_find_child_node_by_name(struct dt_device_node *from, const char *name)
>
> Nit: Overlong line here, and ...
Okay, I will fix it.
> > +static int __init parse_core(struct dt_device_node *core,
> > + unsigned int package_id, unsigned int cluster_id,
> > + unsigned int core_id)
>
> ... bogus indentation e.g. here. Please go though yourself to check style.
Okay.
> > --- /dev/null
> > +++ b/xen/drivers/acpi/topology.c
> > @@ -0,0 +1,38 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +
> > +#include <xen/cpumask.h>
> > +#include <xen/cpu-topology.h>
> > +#include <xen/init.h>
> > +#include <xen/acpi.h>
> > +
> > +/*
> > + * ToDo: Populate the topology information by scanning the ACPI
> > + * PPTT (Processor Properties Topology Table).
>
> Please can this be spelled "TODO:", to stand out more and to be a hit also
> with case sensitive grep for "TODO"?
Okay.
> > --- a/xen/include/xen/acpi.h
> > +++ b/xen/include/xen/acpi.h
> > @@ -101,6 +101,8 @@ void acpi_table_print (struct acpi_table_header
> *header, unsigned long phys_addr
> > void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
> > void acpi_table_print_srat_entry (struct acpi_subtable_header *srat);
> >
> > +void acpi_init_cpu_topology(void);
> > +
> > /* the following four functions are architecture-dependent */
> > void acpi_numa_slit_init (struct acpi_table_slit *slit);
> > void acpi_numa_processor_affinity_init(const struct
> acpi_srat_cpu_affinity *);
> > @@ -133,6 +135,8 @@ static inline int acpi_boot_table_init(void)
> > return 0;
> > }
> >
> > +static inline void acpi_init_cpu_topology(void) {}
>
> This shouldn't be needed. When ACPI=y, acpi_disabled is compile-time true,
> and hence the compiler can and will DCE the call. All it needs to see is a
> declaration, which therefore wants to move outside of the CONFIG_ACPI
> conditional.
okay
> > --- /dev/null
> > +++ b/xen/include/xen/cpu-topology.h
> > @@ -0,0 +1,36 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +
> > +#ifndef XEN_CPU_TOPOLOGY_H
> > +#define XEN_CPU_TOPOLOGY_H
> > +
> > +#include <xen/types.h>
> > +#include <xen/dt-cpu-topology.h>
> > +
> > +struct cpu_topology {
> > + cpumask_t thread_sibling;
> > + cpumask_t core_sibling;
> > + cpumask_t cluster_sibling;
> > +};
>
> With huge NR_CPUS this can be pretty large a struct (of which in init_cpu_topology()
> you allocate an array). Imo you want to use cpumask_var_t here, with allocation added
> as needed.
Okay.
> > +
> > +
>
> Nit: No double blank lines please.
Okay.
Thank you,
Hirokazu Takahashi.
^ permalink raw reply
* Re: [PATCH v3 2/2] drm/panel: add Ilitek ILI7807S panel driver
From: sashiko-bot @ 2026-06-24 9:04 UTC (permalink / raw)
To: Arpit Saini; +Cc: dri-devel, robh, conor+dt, devicetree
In-Reply-To: <20260624-ili7807s-v3-2-ddf37052a289@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Incorrect and non-atomic modification of `dsi->mode_flags` permanently enables Low Power Mode and introduces a data race.
- [High] Backlight `update_status` sends DSI commands without verifying that the panel is powered on, risking DSI host timeouts.
--
commit 2f966f15c21adb82ce5699cdffad22cac6628b98
Author: Arpit Saini <arpit.saini@oss.qualcomm.com>
drm/panel: add Ilitek ILI7807S panel driver
Add a DRM panel driver for the DLC DLC0697 1080x1920@60Hz MIPI DSI
panel based on the Ilitek ILI7807S display controller.
> diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c b/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c
> new file mode 100644
> index 0000000000000..8ddfab2693ec8
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-ilitek-ili7807s.c
[ ... ]
> +static int ili7807s_bl_update_status(struct backlight_device *bl)
> +{
> + struct mipi_dsi_device *dsi = bl_get_data(bl);
> + u16 brightness = backlight_get_brightness(bl);
> + int ret;
> +
[Severity: High]
Does this code send DSI commands without verifying if the panel is powered on?
If the panel regulators are disabled and reset is asserted via
ili7807s_unprepare(), attempting to communicate with it here during a sysfs
backlight update could result in DSI host bus timeouts or hardware lockups.
Should there be a check against a power state tracking flag before
sending the DCS command?
> + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
> +
> + ret = mipi_dsi_dcs_set_display_brightness_large(dsi, brightness);
> +
> + dsi->mode_flags |= MIPI_DSI_MODE_LPM;
[Severity: High]
Does unconditionally setting MIPI_DSI_MODE_LPM here permanently alter the
panel's base operating state?
Since the mode_flags are modified without synchronization with DRM modeset
paths (like ili7807s_on() and ili7807s_off()), could this create a data
race?
Also, the logic clears the flag before the transaction and unconditionally
sets it afterwards, leaving Low Power Mode permanently enabled for
subsequent DSI transmissions.
> +
> + return ret;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624-ili7807s-v3-0-ddf37052a289@oss.qualcomm.com?part=2
^ permalink raw reply
* Re: [PATCH v10 16/31] cxl/extent: Validate DC extent partition
From: Anisa Su @ 2026-06-24 9:04 UTC (permalink / raw)
To: Anisa Su
Cc: linux-cxl, linux-kernel, nvdimm, Dan Williams, Jonathan Cameron,
Davidlohr Bueso, Dave Jiang, Vishal Verma, Ira Weiny,
Alison Schofield, John Groves, Gregory Price, Ira Weiny
In-Reply-To: <def526ee51b647e9256c7e777c6b7bd5cd647f89.1779528761.git.anisa.su@samsung.com>
On Sat, May 23, 2026 at 02:43:10AM -0700, Anisa Su wrote:
> Extend cxl_validate_extent() — the per-extent check of the add pipeline
> to check partition membership.
>
> Resolves an extent's DPA to its containing DC partition. Then based on
> if the partition is shareable:
>
> - Shareable: tag must be non-null and shared_extn_seq must be non-zero
> — multiple hosts reading the same allocation rely on the device-
> stamped 1..n sequence to assemble extents in agreed order.
> - Non-sharable: shared_extn_seq must be zero — sequencing is
> meaningless when only one host consumes the allocation; tag is
> optional (null UUID permitted).
>
> Any cross-mix is a device firmware bug; reject the extent.
>
> Based on patches by John Groves.
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> Signed-off-by: John Groves <John@Groves.net>
> Signed-off-by: Anisa Su <anisa.su@samsung.com>
>
> ---
> Changes:
> [anisa: split out as a separate validation step]
> ---
> drivers/cxl/core/core.h | 4 ++
> drivers/cxl/core/extent.c | 78 +++++++++++++++++++++++++++++++++++++--
> 2 files changed, 79 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
> index 1bae80dbf991..30b6b05b155b 100644
> --- a/drivers/cxl/core/core.h
> +++ b/drivers/cxl/core/core.h
> @@ -179,6 +179,10 @@ int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c);
> int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
> struct access_coordinate *c);
> void memdev_release_extent(struct cxl_memdev_state *mds, struct range *range);
> +const struct cxl_dpa_partition *
> +cxl_extent_dc_partition(struct cxl_memdev_state *mds,
> + struct cxl_extent *extent,
> + struct range *ext_range);
>
> static inline struct device *port_to_host(struct cxl_port *port)
> {
> diff --git a/drivers/cxl/core/extent.c b/drivers/cxl/core/extent.c
> index 94128d06f4ed..b01507022cff 100644
> --- a/drivers/cxl/core/extent.c
> +++ b/drivers/cxl/core/extent.c
> @@ -63,11 +63,55 @@ alloc_tag_group(struct cxl_dax_region *cxlr_dax, uuid_t *uuid)
> return no_free_ptr(group);
> }
>
> +/*
> + * Find the DC (Dynamic Capacity) partition that fully contains @ext_range,
> + * or NULL if the extent falls outside every DC partition on this memdev.
> + * The returned pointer is owned by mds->cxlds.part[] and lives for the
> + * lifetime of the memdev.
> + */
> +const struct cxl_dpa_partition *
> +cxl_extent_dc_partition(struct cxl_memdev_state *mds,
> + struct cxl_extent *extent,
> + struct range *ext_range)
> +{
> + struct cxl_dev_state *cxlds = &mds->cxlds;
> + struct device *dev = mds->cxlds.dev;
> +
From Sashiko: https://sashiko.dev/#/patchset/cover.1779528761.git.anisa.su%40samsung.com?part=16
Sashiko complains about the possibility of end < start in multiple
places. Add a check here for that. Should be sufficient to add the check
here, since every add-able extent passes through here.
if (ext_range->end < ext_range->start) {
dev_err_ratelimited(dev,
"DC extent DPA %pra (%pU) has invalid length (firmware bug)\n",
ext_range, extent->uuid);
return NULL;
}
- Anisa
> + for (int i = 0; i < cxlds->nr_partitions; i++) {
> + struct cxl_dpa_partition *part = &cxlds->part[i];
> + struct range partition_range = {
> + .start = part->res.start,
> + .end = part->res.end,
> + };
> +
> + if (part->mode != CXL_PARTMODE_DYNAMIC_RAM_A)
> + continue;
> +
> + if (range_contains(&partition_range, ext_range)) {
> + dev_dbg(dev, "DC extent DPA %pra (DCR:%pra)(%pU)\n",
> + ext_range, &partition_range, extent->uuid);
> + return part;
> + }
> + }
> +
> + dev_err_ratelimited(dev,
> + "DC extent DPA %pra (%pU) is not in a valid DC partition\n",
> + ext_range, extent->uuid);
> + return NULL;
> +}
> +
> /*
> * Stage 1 of the add pipeline: pure, no allocation. Resolve the extent
> - * to its region/endpoint decoder and ext_range, and verify the range
> - * fits in the resolved endpoint decoder's DPA resource. Further
> - * per-extent invariants layer into this function in subsequent commits.
> + * to its region/endpoint decoder and ext_range, and enforce every
> + * per-extent invariant the device must satisfy:
> + *
> + * - DPA falls inside a Dynamic Capacity partition (cxl_extent_dc_partition).
> + * - CDAT-sharability rules:
> + * sharable: tag must be non-null AND shared_extn_seq != 0
> + * non-sharable: shared_extn_seq must be 0 (tag is optional)
> + * Any cross-mixing is a device firmware bug.
> + * - DPA resolves to an endpoint decoder attached to a region.
> + * - The extent's range is fully contained in that ED's DPA resource.
> *
> * Caller must hold cxl_rwsem.region for read (cxl_dpa_to_region()).
> * On success, @out_cxled / @out_cxlr_dax / @out_ext_range carry the
> @@ -81,6 +125,10 @@ static int cxl_validate_extent(struct cxl_memdev_state *mds,
> {
> u64 start_dpa = le64_to_cpu(extent->start_dpa);
> struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
> + struct device *dev = mds->cxlds.dev;
> + uuid_t *uuid = (uuid_t *)extent->uuid;
> + u16 seq = le16_to_cpu(extent->shared_extn_seq);
> + const struct cxl_dpa_partition *part;
> struct cxl_endpoint_decoder *cxled;
> struct cxl_region *cxlr;
> struct range ext_range = (struct range) {
> @@ -89,6 +137,30 @@ static int cxl_validate_extent(struct cxl_memdev_state *mds,
> };
> struct range ed_range;
>
> + part = cxl_extent_dc_partition(mds, extent, &ext_range);
> + if (!part)
> + return -ENXIO;
> +
> + if (part->perf.shareable) {
> + if (uuid_is_null(uuid)) {
> + dev_err_ratelimited(dev,
> + "DC extent DPA %pra: sharable-partition extent has null tag (firmware bug)\n",
> + &ext_range);
> + return -ENXIO;
> + }
> + if (seq == 0) {
> + dev_err_ratelimited(dev,
> + "DC extent DPA %pra (%pU): sharable-partition extent missing shared_extn_seq (firmware bug)\n",
> + &ext_range, uuid);
> + return -ENXIO;
> + }
> + } else if (seq != 0) {
> + dev_err_ratelimited(dev,
> + "DC extent DPA %pra (%pU): non-sharable partition but shared_extn_seq=%u (firmware bug)\n",
> + &ext_range, uuid, seq);
> + return -ENXIO;
> + }
> +
> cxlr = cxl_dpa_to_region(cxlmd, start_dpa, &cxled);
> if (!cxlr)
> return -ENXIO;
> --
> 2.43.0
>
^ permalink raw reply
* [PATCH 7/7] ARM: dts: rockchip: Add Alientek DLRV1126
From: Yanan He @ 2026-06-24 9:02 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, heiko, andrew+netdev, davem, edumazet,
kuba, pabeni, david.wu, mcoquelin.stm32, alexandre.torgue
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
netdev, linux-stm32, grumpycat921013
In-Reply-To: <20260624-rv1126-alientek-dlrv1126-v1-0-dc42d99f75a7@gmail.com>
The board consists of a CLRV1126F core module and a DLRV1126 carrier
board. The core module contains the RV1126 SoC, eMMC and RK809 PMIC,
while the carrier board provides Ethernet, SD card, AP6212 WiFi and
Bluetooth, PCF8563 RTC, ADC keys, GPIO LEDs and audio connectors.
The board has been tested with Ethernet/NFS boot, eMMC, SD card, SDIO
WiFi enumeration, Bluetooth LE scanning, RTC, ADC keys, GPIO LEDs and
RK809 audio card registration.
Signed-off-by: Yanan He <grumpycat921013@gmail.com>
---
arch/arm/boot/dts/rockchip/Makefile | 1 +
.../dts/rockchip/rv1126-alientek-clrv1126f.dtsi | 277 +++++++++++++++++++++
.../boot/dts/rockchip/rv1126-alientek-dlrv1126.dts | 258 +++++++++++++++++++
3 files changed, 536 insertions(+)
diff --git a/arch/arm/boot/dts/rockchip/Makefile b/arch/arm/boot/dts/rockchip/Makefile
index d0154fd7ff24..e9f9e0ac3bfd 100644
--- a/arch/arm/boot/dts/rockchip/Makefile
+++ b/arch/arm/boot/dts/rockchip/Makefile
@@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rv1108-evb.dtb \
rv1109-relfor-saib.dtb \
rv1109-sonoff-ihost.dtb \
+ rv1126-alientek-dlrv1126.dtb \
rv1126-edgeble-neu2-io.dtb \
rv1126-sonoff-ihost.dtb \
rk3036-evb.dtb \
diff --git a/arch/arm/boot/dts/rockchip/rv1126-alientek-clrv1126f.dtsi b/arch/arm/boot/dts/rockchip/rv1126-alientek-clrv1126f.dtsi
new file mode 100644
index 000000000000..9bee424b1797
--- /dev/null
+++ b/arch/arm/boot/dts/rockchip/rv1126-alientek-clrv1126f.dtsi
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2026 Yanan He <grumpycat921013@gmail.com>
+ */
+
+#include "rv1126.dtsi"
+
+/ {
+ compatible = "alientek,clrv1126f", "rockchip,rv1126";
+
+ aliases {
+ mmc0 = &emmc;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&emmc {
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_cmd &emmc_clk &emmc_rstnout>;
+ rockchip,default-sample-phase = <90>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB1 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ #sound-dai-cells = <0>;
+ clock-output-names = "rk808-clkout1", "rk808-clkout2";
+ clock-names = "mclk";
+ clocks = <&cru MCLK_I2S0_TX_OUT2IO>;
+ assigned-clocks = <&cru MCLK_I2S0_TX_OUT2IO>;
+ assigned-clock-parents = <&cru MCLK_I2S0_TX>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>;
+ rockchip,system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc_buck5>;
+ vcc6-supply = <&vcc_buck5>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc3v3_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+
+ regulators {
+ vdd_npu_vepu: DCDC_REG1 {
+ regulator-name = "vdd_npu_vepu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <650000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc3v3_sys: DCDC_REG4 {
+ regulator-name = "vcc3v3_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_buck5: DCDC_REG5 {
+ regulator-name = "vcc_buck5";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2200000>;
+ };
+ };
+
+ vcc_0v8: LDO_REG1 {
+ regulator-name = "vcc_0v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc1v8_pmu: LDO_REG2 {
+ regulator-name = "vcc1v8_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd0v8_pmu: LDO_REG3 {
+ regulator-name = "vcc0v8_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <800000>;
+ };
+ };
+
+ vcc_1v8: LDO_REG4 {
+ regulator-name = "vcc_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc_dovdd: LDO_REG5 {
+ regulator-name = "vcc_dovdd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_dvdd: LDO_REG6 {
+ regulator-name = "vcc_dvdd";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_avdd: LDO_REG7 {
+ regulator-name = "vcc_avdd";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG8 {
+ regulator-name = "vccio_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc3v3_sd: LDO_REG9 {
+ regulator-name = "vcc3v3_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_5v0: SWITCH_REG1 {
+ regulator-name = "vcc_5v0";
+ };
+
+ vcc_3v3: SWITCH_REG2 {
+ regulator-name = "vcc_3v3";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
+&pinctrl {
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio0-supply = <&vcc3v3_sys>;
+ pmuio1-supply = <&vcc3v3_sys>;
+ vccio1-supply = <&vcc_1v8>;
+ vccio2-supply = <&vccio_sd>;
+ vccio3-supply = <&vcc_1v8>;
+ vccio4-supply = <&vcc_3v3>;
+ vccio5-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_3v3>;
+ vccio7-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/rockchip/rv1126-alientek-dlrv1126.dts b/arch/arm/boot/dts/rockchip/rv1126-alientek-dlrv1126.dts
new file mode 100644
index 000000000000..c8123a3c4746
--- /dev/null
+++ b/arch/arm/boot/dts/rockchip/rv1126-alientek-dlrv1126.dts
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2026 Yanan He <grumpycat921013@gmail.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "rv1126-alientek-clrv1126f.dtsi"
+
+/ {
+ model = "Alientek ATK-DLRV1126";
+ compatible = "alientek,dlrv1126", "alientek,clrv1126f", "rockchip,rv1126";
+
+ aliases {
+ ethernet0 = &gmac;
+ mmc1 = &sdio;
+ mmc2 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 0>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-esc {
+ label = "esc";
+ linux,code = <KEY_ESC>;
+ press-threshold-microvolt = <0>;
+ };
+
+ button-right {
+ label = "right";
+ linux,code = <KEY_RIGHT>;
+ press-threshold-microvolt = <400781>;
+ };
+
+ button-left {
+ label = "left";
+ linux,code = <KEY_LEFT>;
+ press-threshold-microvolt = <801562>;
+ };
+
+ button-menu {
+ label = "menu";
+ linux,code = <KEY_MENU>;
+ press-threshold-microvolt = <1198828>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ label = "sys-led";
+ gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ default-state = "on";
+ };
+
+ led-1 {
+ label = "user-led";
+ gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ default-state = "on";
+ };
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "Analog RK809";
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Speaker", "Speaker",
+ "Headphone", "Headphones",
+ "Microphone", "Mic Jack";
+ simple-audio-card,routing =
+ "Speaker", "SPKO",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "MICL", "Mic Jack";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&rk809>;
+ };
+ };
+
+ vcc5v0_sys: regulator-vcc5v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ sdio_pwrseq: pwrseq-sdio {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h>;
+ reset-gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_LOW>;
+ post-power-on-delay-ms = <200>;
+ power-off-delay-us = <20000>;
+ };
+};
+
+&i2c5 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ pcf8563: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <RK_PD0 IRQ_TYPE_LEVEL_LOW>;
+ clock-output-names = "xin32k";
+ };
+};
+
+&gmac {
+ phy-mode = "rgmii";
+ clock_in_out = "input";
+ assigned-clocks = <&cru CLK_GMAC_SRC>, <&cru CLK_GMAC_TX_RX>,
+ <&cru CLK_GMAC_ETHERNET_OUT>;
+ assigned-clock-parents = <&cru CLK_GMAC_SRC_M1>,
+ <&cru RGMII_MODE_CLK>;
+ assigned-clock-rates = <125000000>, <0>, <25000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmiim1_miim &rgmiim1_bus2 &rgmiim1_bus4
+ &clk_out_ethernetm1_pins>;
+ tx_delay = <0x2a>;
+ rx_delay = <0x1a>;
+ phy-handle = <&phy>;
+ status = "okay";
+};
+
+&mdio {
+ phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ clocks = <&cru CLK_GMAC_ETHERNET_OUT>;
+ pinctrl-names = "default";
+ pinctrl-0 = <ð_phy_rst>;
+ reset-gpios = <&gpio3 RK_PA0 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ };
+};
+
+&pinctrl {
+ ethernet {
+ eth_phy_rst: eth-phy-rst {
+ rockchip,pins = <3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ bt {
+ bt_enable: bt-enable {
+ rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_dev: bt-wake-dev {
+ rockchip,pins = <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_host: bt-wake-host {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wifi {
+ wifi_enable_h: wifi-enable-h {
+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&sdio {
+ bus-width = <4>;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ max-frequency = <25000000>;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_clk &sdmmc1_cmd &sdmmc1_bus4>;
+ rockchip,default-sample-phase = <90>;
+ vmmc-supply = <&vcc3v3_sd>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ card-detect-delay = <200>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_bus4 &sdmmc0_det>;
+ rockchip,default-sample-phase = <90>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_sd>;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_ctsn &uart0_rtsn>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43430a1-bt";
+ shutdown-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_HIGH>;
+ device-wakeup-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
+ clocks = <&rk809 1>;
+ clock-names = "lpo";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA5 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "host-wakeup";
+ max-speed = <115200>;
+ vbat-supply = <&vcc_3v3>;
+ vddio-supply = <&vcc_1v8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_enable>, <&bt_wake_dev>, <&bt_wake_host>;
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&i2s0 {
+ rockchip,trcm-sync-tx-only;
+ rockchip,i2s-rx-route = <3 1 2 0>;
+ rockchip,i2s-tx-route = <0 1 2 3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0m0_sclk_tx>,
+ <&i2s0m0_mclk>,
+ <&i2s0m0_lrck_tx>,
+ <&i2s0m0_sdo0>,
+ <&i2s0m0_sdo1_sdi3>;
+ status = "okay";
+};
--
2.54.0
^ permalink raw reply related
* [PATCH 7/7] ARM: dts: rockchip: Add Alientek DLRV1126
From: Yanan He @ 2026-06-24 9:02 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, heiko, andrew+netdev, davem, edumazet,
kuba, pabeni, david.wu, mcoquelin.stm32, alexandre.torgue
Cc: devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
netdev, linux-stm32, grumpycat921013
In-Reply-To: <20260624-rv1126-alientek-dlrv1126-v1-0-dc42d99f75a7@gmail.com>
The board consists of a CLRV1126F core module and a DLRV1126 carrier
board. The core module contains the RV1126 SoC, eMMC and RK809 PMIC,
while the carrier board provides Ethernet, SD card, AP6212 WiFi and
Bluetooth, PCF8563 RTC, ADC keys, GPIO LEDs and audio connectors.
The board has been tested with Ethernet/NFS boot, eMMC, SD card, SDIO
WiFi enumeration, Bluetooth LE scanning, RTC, ADC keys, GPIO LEDs and
RK809 audio card registration.
Signed-off-by: Yanan He <grumpycat921013@gmail.com>
---
arch/arm/boot/dts/rockchip/Makefile | 1 +
.../dts/rockchip/rv1126-alientek-clrv1126f.dtsi | 277 +++++++++++++++++++++
.../boot/dts/rockchip/rv1126-alientek-dlrv1126.dts | 258 +++++++++++++++++++
3 files changed, 536 insertions(+)
diff --git a/arch/arm/boot/dts/rockchip/Makefile b/arch/arm/boot/dts/rockchip/Makefile
index d0154fd7ff24..e9f9e0ac3bfd 100644
--- a/arch/arm/boot/dts/rockchip/Makefile
+++ b/arch/arm/boot/dts/rockchip/Makefile
@@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
rv1108-evb.dtb \
rv1109-relfor-saib.dtb \
rv1109-sonoff-ihost.dtb \
+ rv1126-alientek-dlrv1126.dtb \
rv1126-edgeble-neu2-io.dtb \
rv1126-sonoff-ihost.dtb \
rk3036-evb.dtb \
diff --git a/arch/arm/boot/dts/rockchip/rv1126-alientek-clrv1126f.dtsi b/arch/arm/boot/dts/rockchip/rv1126-alientek-clrv1126f.dtsi
new file mode 100644
index 000000000000..9bee424b1797
--- /dev/null
+++ b/arch/arm/boot/dts/rockchip/rv1126-alientek-clrv1126f.dtsi
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2026 Yanan He <grumpycat921013@gmail.com>
+ */
+
+#include "rv1126.dtsi"
+
+/ {
+ compatible = "alientek,clrv1126f", "rockchip,rv1126";
+
+ aliases {
+ mmc0 = &emmc;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&emmc {
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_cmd &emmc_clk &emmc_rstnout>;
+ rockchip,default-sample-phase = <90>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB1 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ #sound-dai-cells = <0>;
+ clock-output-names = "rk808-clkout1", "rk808-clkout2";
+ clock-names = "mclk";
+ clocks = <&cru MCLK_I2S0_TX_OUT2IO>;
+ assigned-clocks = <&cru MCLK_I2S0_TX_OUT2IO>;
+ assigned-clock-parents = <&cru MCLK_I2S0_TX>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>;
+ rockchip,system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc_buck5>;
+ vcc6-supply = <&vcc_buck5>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc3v3_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+
+ regulators {
+ vdd_npu_vepu: DCDC_REG1 {
+ regulator-name = "vdd_npu_vepu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <650000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc3v3_sys: DCDC_REG4 {
+ regulator-name = "vcc3v3_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_buck5: DCDC_REG5 {
+ regulator-name = "vcc_buck5";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2200000>;
+ };
+ };
+
+ vcc_0v8: LDO_REG1 {
+ regulator-name = "vcc_0v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc1v8_pmu: LDO_REG2 {
+ regulator-name = "vcc1v8_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd0v8_pmu: LDO_REG3 {
+ regulator-name = "vcc0v8_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <800000>;
+ };
+ };
+
+ vcc_1v8: LDO_REG4 {
+ regulator-name = "vcc_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc_dovdd: LDO_REG5 {
+ regulator-name = "vcc_dovdd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_dvdd: LDO_REG6 {
+ regulator-name = "vcc_dvdd";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_avdd: LDO_REG7 {
+ regulator-name = "vcc_avdd";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG8 {
+ regulator-name = "vccio_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc3v3_sd: LDO_REG9 {
+ regulator-name = "vcc3v3_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_5v0: SWITCH_REG1 {
+ regulator-name = "vcc_5v0";
+ };
+
+ vcc_3v3: SWITCH_REG2 {
+ regulator-name = "vcc_3v3";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
+&pinctrl {
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio0-supply = <&vcc3v3_sys>;
+ pmuio1-supply = <&vcc3v3_sys>;
+ vccio1-supply = <&vcc_1v8>;
+ vccio2-supply = <&vccio_sd>;
+ vccio3-supply = <&vcc_1v8>;
+ vccio4-supply = <&vcc_3v3>;
+ vccio5-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_3v3>;
+ vccio7-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/rockchip/rv1126-alientek-dlrv1126.dts b/arch/arm/boot/dts/rockchip/rv1126-alientek-dlrv1126.dts
new file mode 100644
index 000000000000..c8123a3c4746
--- /dev/null
+++ b/arch/arm/boot/dts/rockchip/rv1126-alientek-dlrv1126.dts
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2026 Yanan He <grumpycat921013@gmail.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "rv1126-alientek-clrv1126f.dtsi"
+
+/ {
+ model = "Alientek ATK-DLRV1126";
+ compatible = "alientek,dlrv1126", "alientek,clrv1126f", "rockchip,rv1126";
+
+ aliases {
+ ethernet0 = &gmac;
+ mmc1 = &sdio;
+ mmc2 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 0>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-esc {
+ label = "esc";
+ linux,code = <KEY_ESC>;
+ press-threshold-microvolt = <0>;
+ };
+
+ button-right {
+ label = "right";
+ linux,code = <KEY_RIGHT>;
+ press-threshold-microvolt = <400781>;
+ };
+
+ button-left {
+ label = "left";
+ linux,code = <KEY_LEFT>;
+ press-threshold-microvolt = <801562>;
+ };
+
+ button-menu {
+ label = "menu";
+ linux,code = <KEY_MENU>;
+ press-threshold-microvolt = <1198828>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ label = "sys-led";
+ gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ default-state = "on";
+ };
+
+ led-1 {
+ label = "user-led";
+ gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "none";
+ default-state = "on";
+ };
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "Analog RK809";
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Speaker", "Speaker",
+ "Headphone", "Headphones",
+ "Microphone", "Mic Jack";
+ simple-audio-card,routing =
+ "Speaker", "SPKO",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "MICL", "Mic Jack";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&rk809>;
+ };
+ };
+
+ vcc5v0_sys: regulator-vcc5v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ sdio_pwrseq: pwrseq-sdio {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h>;
+ reset-gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_LOW>;
+ post-power-on-delay-ms = <200>;
+ power-off-delay-us = <20000>;
+ };
+};
+
+&i2c5 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ pcf8563: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <RK_PD0 IRQ_TYPE_LEVEL_LOW>;
+ clock-output-names = "xin32k";
+ };
+};
+
+&gmac {
+ phy-mode = "rgmii";
+ clock_in_out = "input";
+ assigned-clocks = <&cru CLK_GMAC_SRC>, <&cru CLK_GMAC_TX_RX>,
+ <&cru CLK_GMAC_ETHERNET_OUT>;
+ assigned-clock-parents = <&cru CLK_GMAC_SRC_M1>,
+ <&cru RGMII_MODE_CLK>;
+ assigned-clock-rates = <125000000>, <0>, <25000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmiim1_miim &rgmiim1_bus2 &rgmiim1_bus4
+ &clk_out_ethernetm1_pins>;
+ tx_delay = <0x2a>;
+ rx_delay = <0x1a>;
+ phy-handle = <&phy>;
+ status = "okay";
+};
+
+&mdio {
+ phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ clocks = <&cru CLK_GMAC_ETHERNET_OUT>;
+ pinctrl-names = "default";
+ pinctrl-0 = <ð_phy_rst>;
+ reset-gpios = <&gpio3 RK_PA0 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ };
+};
+
+&pinctrl {
+ ethernet {
+ eth_phy_rst: eth-phy-rst {
+ rockchip,pins = <3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ bt {
+ bt_enable: bt-enable {
+ rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_dev: bt-wake-dev {
+ rockchip,pins = <1 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_wake_host: bt-wake-host {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ wifi {
+ wifi_enable_h: wifi-enable-h {
+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&sdio {
+ bus-width = <4>;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ max-frequency = <25000000>;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_clk &sdmmc1_cmd &sdmmc1_bus4>;
+ rockchip,default-sample-phase = <90>;
+ vmmc-supply = <&vcc3v3_sd>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ card-detect-delay = <200>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_bus4 &sdmmc0_det>;
+ rockchip,default-sample-phase = <90>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_sd>;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_ctsn &uart0_rtsn>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43430a1-bt";
+ shutdown-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_HIGH>;
+ device-wakeup-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
+ clocks = <&rk809 1>;
+ clock-names = "lpo";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA5 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "host-wakeup";
+ max-speed = <115200>;
+ vbat-supply = <&vcc_3v3>;
+ vddio-supply = <&vcc_1v8>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_enable>, <&bt_wake_dev>, <&bt_wake_host>;
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&i2s0 {
+ rockchip,trcm-sync-tx-only;
+ rockchip,i2s-rx-route = <3 1 2 0>;
+ rockchip,i2s-tx-route = <0 1 2 3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0m0_sclk_tx>,
+ <&i2s0m0_mclk>,
+ <&i2s0m0_lrck_tx>,
+ <&i2s0m0_sdo0>,
+ <&i2s0m0_sdo1_sdi3>;
+ status = "okay";
+};
--
2.54.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* Re: [PATCH v1] kernel: add a simple timer based software watchpoint
From: Thomas Gleixner @ 2026-06-24 9:04 UTC (permalink / raw)
To: Feng Tang, David Hildenbrand (Arm)
Cc: Andrew Morton, Petr Mladek, Steven Rostedt, paulmck,
Douglas Anderson, Peter Zijlstra, Vlastimil Babka, linux-kernel,
Ard Biesheuvel
In-Reply-To: <ajpDNxhOS-6l6LdP@U-2FWC9VHC-2323.local>
On Tue, Jun 23 2026 at 16:26, Feng Tang wrote:
> On Mon, Jun 22, 2026 at 04:13:37PM +0200, David Hildenbrand (Arm) wrote:
> As discussed in RFC patch review, this debug feature is similar to
> soft/hard lockup detector and task-hung detector, should I make the control
How is this very specialized ad hoc debug magic in any way similar to
generally useful and just working debug mechanism like the lockup or
hung detector? Those are just turned on, do not need a boatload of
command line parameters and are generally useful.
Your debug magic is a workaround for a disfunctional hardware debugger,
which means it's going to be used by three people twice a year if at
all. Seriously?
Thanks,
tglx
^ permalink raw reply
* Re: [PATCH mm-hotfixses] Revert "mm: limit filemap_fault readahead to VMA boundaries"
From: David Hildenbrand (Arm) @ 2026-06-24 9:04 UTC (permalink / raw)
To: Frederick Mayle, Pedro Falcato
Cc: Suren Baghdasaryan, Matthew Wilcox, Andrew Morton,
Lorenzo Stoakes, Jan Kara, Kalesh Singh, linux-fsdevel, linux-mm,
linux-kernel
In-Reply-To: <CAHCxdc4tBb+U7LrrHH+sTEr5Mv_0hJKV6TMZNrrjb-p28sPBcw@mail.gmail.com>
On 6/23/26 21:28, Frederick Mayle wrote:
> On Mon, Jun 22, 2026 at 3:29 PM Pedro Falcato <pfalcato@suse.de> wrote:
>>
>> On Mon, Jun 22, 2026 at 10:57:30AM -0700, Suren Baghdasaryan wrote:
>>>
>>> Thanks for the suggestion! That sounds sensible to me.
>>
>> I don't think this works. Here's an example readelf -a from a random,
>> trivial ELF I have:
>>
>> pfalcato@pedro-suse:~/linux> cc -g main.c
>> pfalcato@pedro-suse:~/linux> readelf -a a.out
>> ELF Header:
>> Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
>> Class: ELF64
>> Data: 2's complement, little endian
>> Version: 1 (current)
>> OS/ABI: UNIX - System V
>> ABI Version: 0
>> Type: EXEC (Executable file)
>> Machine: Advanced Micro Devices X86-64
>> Version: 0x1
>> Entry point address: 0x401040
>> Start of program headers: 64 (bytes into file)
>> Start of section headers: 18448 (bytes into file)
>> Flags: 0x0
>> Size of this header: 64 (bytes)
>> Size of program headers: 56 (bytes)
>> Number of program headers: 14
>> Size of section headers: 64 (bytes)
>> Number of section headers: 38
>> Section header string table index: 37
>>
>> Section Headers:
>> [Nr] Name Type Address Offset
>> Size EntSize Flags Link Info Align
>> [ 0] NULL 0000000000000000 00000000
>> 0000000000000000 0000000000000000 0 0 0
>> [ 1] .note.gnu.pr[...] NOTE 0000000000400350 00000350
>> 0000000000000040 0000000000000000 A 0 0 8
>> [ 2] .note.gnu.bu[...] NOTE 0000000000400390 00000390
>> 0000000000000024 0000000000000000 A 0 0 4
>> [ 3] .interp PROGBITS 00000000004003b4 000003b4
>> 000000000000001c 0000000000000000 A 0 0 1
>> [ 4] .hash HASH 00000000004003d0 000003d0
>> 0000000000000024 0000000000000004 A 6 0 8
>> [ 5] .gnu.hash GNU_HASH 00000000004003f8 000003f8
>> 000000000000001c 0000000000000000 A 6 0 8
>> [ 6] .dynsym DYNSYM 0000000000400418 00000418
>> 0000000000000060 0000000000000018 A 7 1 8
>> [ 7] .dynstr STRTAB 0000000000400478 00000478
>> 000000000000004a 0000000000000000 A 0 0 1
>> [ 8] .gnu.version VERSYM 00000000004004c2 000004c2
>> 0000000000000008 0000000000000002 A 6 0 2
>> [ 9] .gnu.version_r VERNEED 00000000004004d0 000004d0
>> 0000000000000030 0000000000000000 A 7 1 8
>> [10] .rela.dyn RELA 0000000000400500 00000500
>> 0000000000000030 0000000000000018 A 6 0 8
>> [11] .rela.plt RELA 0000000000400530 00000530
>> 0000000000000018 0000000000000018 AI 6 24 8
>> [12] .init PROGBITS 0000000000401000 00001000
>> 000000000000001b 0000000000000000 AX 0 0 4
>> [13] .plt PROGBITS 0000000000401020 00001020
>> 0000000000000020 0000000000000010 AX 0 0 16
>> [14] .text PROGBITS 0000000000401040 00001040
>> 000000000000011b 0000000000000000 AX 0 0 16
>> [15] .fini PROGBITS 000000000040115c 0000115c
>> 000000000000000d 0000000000000000 AX 0 0 4
>> [16] .rodata PROGBITS 0000000000402000 00002000
>> 0000000000000004 0000000000000004 AM 0 0 4
>> [17] .eh_frame_hdr PROGBITS 0000000000402004 00002004
>> 000000000000002c 0000000000000000 A 0 0 4
>> [18] .eh_frame PROGBITS 0000000000402030 00002030
>> 0000000000000088 0000000000000000 A 0 0 8
>> [19] .note.ABI-tag NOTE 00000000004020b8 000020b8
>> 0000000000000020 0000000000000000 A 0 0 4
>> [20] .init_array INIT_ARRAY 0000000000403de8 00002de8
>> 0000000000000008 0000000000000008 WA 0 0 8
>> [21] .fini_array FINI_ARRAY 0000000000403df0 00002df0
>> 0000000000000008 0000000000000008 WA 0 0 8
>> [22] .dynamic DYNAMIC 0000000000403df8 00002df8
>> 00000000000001e0 0000000000000010 WA 7 0 8
>> [23] .got PROGBITS 0000000000403fd8 00002fd8
>> 0000000000000010 0000000000000008 WA 0 0 8
>> [24] .got.plt PROGBITS 0000000000403fe8 00002fe8
>> 0000000000000020 0000000000000008 WA 0 0 8
>> [25] .data PROGBITS 0000000000404008 00003008
>> 0000000000000010 0000000000000000 WA 0 0 8
>> [26] .bss NOBITS 0000000000404018 00003018
>> 0000000000000008 0000000000000000 WA 0 0 1
>> [27] .comment PROGBITS 0000000000000000 00003018
>> 0000000000000019 0000000000000001 MS 0 0 1
>> [28] .debug_aranges PROGBITS 0000000000000000 00003040
>> 0000000000000150 0000000000000000 0 0 16
>> [29] .debug_info PROGBITS 0000000000000000 00003190
>> 0000000000000444 0000000000000000 0 0 1
>> [30] .debug_abbrev PROGBITS 0000000000000000 000035d4
>> 0000000000000245 0000000000000000 0 0 1
>> [31] .debug_line PROGBITS 0000000000000000 00003819
>> 0000000000000274 0000000000000000 0 0 1
>> [32] .debug_str PROGBITS 0000000000000000 00003a8d
>> 0000000000000540 0000000000000001 MS 0 0 1
>> [33] .debug_line_str PROGBITS 0000000000000000 00003fcd
>> 0000000000000163 0000000000000001 MS 0 0 1
>> [34] .debug_rnglists PROGBITS 0000000000000000 00004130
>> 0000000000000042 0000000000000000 0 0 1
>> [35] .symtab SYMTAB 0000000000000000 00004178
>> 0000000000000360 0000000000000018 36 20 8
>> [36] .strtab STRTAB 0000000000000000 000044d8
>> 00000000000001bc 0000000000000000 0 0 1
>> [37] .shstrtab STRTAB 0000000000000000 00004694
>> 0000000000000176 0000000000000000 0 0 1
>> Key to Flags:
>> W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
>> L (link order), O (extra OS processing required), G (group), T (TLS),
>> C (compressed), x (unknown), o (OS specific), E (exclude),
>> D (mbind), l (large), p (processor specific)
>>
>> Notice the section header table, and how it starts after program text and
>> program data, and how all the other ELF gunk (debug info, symtab,
>> strtab(s)) also goes after .data. So (mostly) the real problematic readahead
>> would be on the RW VMA that covers .data.
>>
>> (This also matches my understanding of linkers, where they generally do
>> (to put it simply) ELF headers - program headers - .text - .data - .bss, with
>> stripable gunk after it.)
>>
>> It's also the case that synchronous RA on VM_EXEC is already pretty
>> conservative and limited, see the big if (vm_flags & VM_EXEC) in
>> do_sync_mmap_readahead(). (I think the underlying logic behind also
>> implies that async RA will not be started against these pages, but I
>> am not sure).
>>
>> --
>> Pedro
>
> Yes, I think readahead of VM_EXEC is already restricted to the VMA.
> Maybe there is an edge case where someone does buffered reads on an
> ELF file, leaving a PG_readahead flag inside the VM_EXEC range, then
> it could trigger async readahead beyond the end, but that sounds
> minor.
>
> For next steps: Suppose we show the mmap usage in this video encoder
> is significantly inefficient compared to buffered reads or a big mmap
> and that project accepts a contribution to move away from the small
> mmaps. Would we be comfortable attempting this again as is? Probably
> there would be a lag before all users of the encoder update and they
> may see this bad perf.
How could you be sure that there isn't some other proprietary (or even just
another open-source) software out there that relies on similar things, but
doesn't provide easy benchmarks that can easily catch this?
--
Cheers,
David
^ permalink raw reply
* Re: [PATCH bpf 1/2] bpf: Keep fastcall spills for helper stack reads
From: sashiko-bot @ 2026-06-24 9:04 UTC (permalink / raw)
To: Nuoqi Gui; +Cc: bpf
In-Reply-To: <20260624-f01-12-fastcall-helper-stack-read-v1-1-e0a86085ef77@mails.tsinghua.edu.cn>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] check_stack_read_fixed_off passes the wrong execution frame to check_fastcall_stack_contract
- [High] fastcall_stack_off minimum bound logic leaves longer fastcall patterns unprotected
--
commit 8cfed53d5c0d5c6188360232f775d8b94b125599
Author: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
bpf: Keep fastcall spills for helper stack reads
The fastcall spill/fill rewrite is only sound while the stack slots used by
the pattern are not accessed outside the pattern. Direct stack loads and
stores already call check_fastcall_stack_contract() to enforce this.
Helper and kfunc memory-argument checks can validate PTR_TO_STACK reads
through check_stack_range_initialized() without applying the same contract.
When such a read overlaps a fastcall spill slot,
bpf_remove_fastcall_spills_fills() can still remove the spill/fill pair.
It can then shrink the subprogram stack depth even though a helper or kfunc
reads that stack address.
Apply check_fastcall_stack_contract() from check_stack_range_initialized()
after the concrete stack range is known. Zero-sized accesses do not read or
write memory, so leave the fastcall optimization unchanged for those.
Fixes: 5b5f51bff1b66 ("bpf: no_caller_saved_registers attribute for helper calls")
Signed-off-by: Nuoqi Gui <gnq25@mails.tsinghua.edu.cn>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 69d75515ed3f7..592da530bdc5a 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -6874,6 +6874,10 @@ static int check_stack_range_initialized(
> max_off = reg->smax_value + off;
> }
>
> + if (access_size)
> + check_fastcall_stack_contract(env, state, env->insn_idx,
> + min_off);
> +
[Severity: High]
This isn't a bug introduced by this patch, but while reviewing this change I
noticed a pre-existing issue in check_stack_read_fixed_off() with how it
passes execution frames to check_fastcall_stack_contract().
In check_stack_read_fixed_off():
struct bpf_verifier_state *vstate = env->cur_state;
struct bpf_func_state *state = vstate->frame[vstate->curframe];
...
check_fastcall_stack_contract(env, state, env->insn_idx, off);
Here, the local state variable evaluates to the current execution frame
(the callee), instead of reg_state which is the frame where the stack memory
actually resides (and can be the caller).
If a BPF subprogram is passed a pointer to its caller's stack and reads a
stack slot that overlaps with a fastcall spill slot in the caller, couldn't
the fastcall bounds be checked against the wrong subprogram's metadata?
Could this cause the verifier to fail to disable the fastcall rewrite for
the caller, resulting in uninitialized stack memory reads when
bpf_remove_fastcall_spills_fills() removes the caller's spill instructions?
[Severity: High]
This is a pre-existing issue, but I also noticed a potential problem in
mark_fastcall_pattern_for_call() with how it tracks fastcall stack boundaries:
subprog->fastcall_stack_off = min(subprog->fastcall_stack_off, off);
Because off is a negative stack offset that moves closer to 0 for longer
patterns, using min() incorrectly shrinks the protected stack region to the
upper bound of the shortest fastcall pattern.
If a BPF subprogram contains multiple fastcall helper patterns of different
lengths (for example, Call A with 1 spill ending at offset -24, and Call B
with 2 spills ending at offset -16), couldn't this expose the upper spill
slots of any longer fastcall patterns?
If a program performs a direct memory access to the highest spill slot (-16)
of the longer pattern outside of the fastcall block, the verifier might
mistakenly preserve the fastcall optimization, removing the spills and
causing uninitialized memory reads at runtime.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624-f01-12-fastcall-helper-stack-read-v1-0-e0a86085ef77@mails.tsinghua.edu.cn?part=1
^ permalink raw reply
* Re: [PATCH] ALSA: seq: Fix uninitialised heap leak in snd_seq_event_dup()
From: Takashi Iwai @ 2026-06-24 9:03 UTC (permalink / raw)
To: HyeongJun An
Cc: Takashi Iwai, Jaroslav Kysela, linux-sound, linux-kernel, stable
In-Reply-To: <20260623233841.853326-1-sammiee5311@gmail.com>
On Wed, 24 Jun 2026 01:38:40 +0200,
HyeongJun An wrote:
>
> snd_seq_event_dup() copies an incoming event into a pool cell and, in
> the UMP-enabled build, clears the trailing cell->ump.raw.extra word that
> the memcpy() did not cover. The guard deciding whether to clear it
> compares the copied size against sizeof(cell->event):
>
> memcpy(&cell->ump, event, size);
> if (size < sizeof(cell->event))
> cell->ump.raw.extra = 0;
>
> For a legacy (non-UMP) event, size == sizeof(struct snd_seq_event) ==
> sizeof(cell->event), so the condition is false and the extra word keeps
> stale data. The cell pool is allocated with kvmalloc() (not zeroed) and
> cells are reused via a free list, so that word holds uninitialised heap
> or leftover event data.
>
> When such a cell is delivered to a UMP client (client->midi_version > 0)
> that set SNDRV_SEQ_FILTER_NO_CONVERT -- so the legacy event reaches it
> unconverted -- snd_seq_read() reads it out as the larger struct
> snd_seq_ump_event and copies the stale word to user space, a 4-byte
> kernel heap infoleak to an unprivileged /dev/snd/seq client.
>
> Compare against sizeof(cell->ump) instead, so the trailing word is zeroed
> for every event shorter than the UMP cell.
>
> Fixes: 46397622a3fa ("ALSA: seq: Add UMP support")
> Cc: stable@vger.kernel.org
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
Applied now. Thanks.
Takashi
^ permalink raw reply
* [PATCH v4] io_uring: annotate remote tasks for kcoverage
From: Robert Femmer @ 2026-06-24 9:01 UTC (permalink / raw)
To: io-uring
Cc: Jens Axboe, Dmitry Vyukov, Andrey Konovalov, kasan-dev, Jann Horn,
Robert Femmer
In-Reply-To: <CAG48ez02Sio8ZENVK3gUWM+8j6NgG9LxtnDV=v+FSqsqs_KfnA@mail.gmail.com>
Fuzzers use coverage information to guide generation of test cases
towards new or interesting code paths. Syzkaller, specifically, makes
use kcoverage (CONFIG_KCOV). Coverage information is not collected for
kernel tasks unless annotated by kcov_remote_start and kcov_remote_stop.
This patch annotates io-uring's work queue and sqpoll tasks.
Depends-On: 20260430-kcov-refactor-common-handle-v1-1-23a0c7a0ba38@google.com
Signed-off-by: Robert Femmer <robert@fmmr.tech>
---
include/linux/io_uring_types.h | 2 ++
io_uring/io-wq.c | 5 +++++
io_uring/io_uring.c | 2 ++
io_uring/sqpoll.c | 3 +++
4 files changed, 12 insertions(+)
diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
index 244392026c6d..b6590b2b350c 100644
--- a/include/linux/io_uring_types.h
+++ b/include/linux/io_uring_types.h
@@ -504,6 +504,8 @@ struct io_ring_ctx {
struct io_mapped_region ring_region;
/* used for optimised request parameter and wait argument passing */
struct io_mapped_region param_region;
+
+ struct kcov_common_handle_id kcov_handle;
};
/*
diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
index 8cc7b47d3089..173299dfc9c2 100644
--- a/io_uring/io-wq.c
+++ b/io_uring/io-wq.c
@@ -19,6 +19,7 @@
#include <linux/mmu_context.h>
#include <linux/sched/sysctl.h>
#include <uapi/linux/io_uring.h>
+#include <linux/kcov.h>
#include "io-wq.h"
#include "slist.h"
@@ -639,6 +640,7 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
/* handle a whole dependent link */
do {
struct io_wq_work *next_hashed, *linked;
+ struct io_kiocb *req;
unsigned int work_flags = atomic_read(&work->flags);
unsigned int hash = __io_wq_is_hashed(work_flags)
? __io_get_work_hash(work_flags)
@@ -649,7 +651,10 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
if (do_kill &&
(work_flags & IO_WQ_WORK_UNBOUND))
atomic_or(IO_WQ_WORK_CANCEL, &work->flags);
+ req = container_of(work, struct io_kiocb, work);
+ kcov_remote_start_common(req->ctx->kcov_handle);
io_wq_submit_work(work);
+ kcov_remote_stop();
io_assign_current_work(worker, NULL);
linked = io_wq_free_work(work);
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 103b6c88f252..ab7c3e45e238 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -59,6 +59,7 @@
#include <linux/audit.h>
#include <linux/security.h>
#include <linux/jump_label.h>
+#include <linux/kcov.h>
#define CREATE_TRACE_POINTS
#include <trace/events/io_uring.h>
@@ -293,6 +294,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
INIT_HLIST_HEAD(&ctx->cancelable_uring_cmd);
io_napi_init(ctx);
mutex_init(&ctx->mmap_lock);
+ ctx->kcov_handle = kcov_common_handle();
return ctx;
diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c
index 46c12afec73e..aafb640d3b2f 100644
--- a/io_uring/sqpoll.c
+++ b/io_uring/sqpoll.c
@@ -13,6 +13,7 @@
#include <linux/cpuset.h>
#include <linux/sched/cputime.h>
#include <linux/io_uring.h>
+#include <linux/kcov.h>
#include <uapi/linux/io_uring.h>
@@ -342,10 +343,12 @@ static int io_sq_thread(void *data)
cap_entries = !list_is_singular(&sqd->ctx_list);
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
+ kcov_remote_start_common(ctx->kcov_handle);
int ret = __io_sq_thread(ctx, sqd, cap_entries, &ist);
if (!sqt_spin && (ret > 0 || !list_empty(&ctx->iopoll_list)))
sqt_spin = true;
+ kcov_remote_stop();
}
if (io_sq_tw(&retry_list, IORING_TW_CAP_ENTRIES_VALUE))
sqt_spin = true;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2 0/4] arm64: Add HOTPLUG_PARALLEL support for secondary CPUs
From: Jinjie Ruan @ 2026-06-24 9:02 UTC (permalink / raw)
To: catalin.marinas, will, tsbogend, pjw, palmer, aou, alex, tglx,
mingo, bp, dave.hansen, hpa, peterz, kees, nathan, linusw,
jpoimboe, lukas.bulwahn, ryan.roberts, ojeda, maz, timothy.hayes,
lpieralisi, thuth, menglong8.dong, oupton, yeoreum.yun,
miko.lenczewski, broonie, kevin.brodsky, james.clark, tabba,
mrigendra.chaubey, arnd, anshuman.khandual, x86, linux-kernel,
linux-arm-kernel, linux-mips, linux-riscv, apatel, mhklinux
In-Reply-To: <20260618092444.1316336-1-ruanjinjie@huawei.com>
Please ignore this patchset, will update in v3.
On 6/18/2026 5:24 PM, Jinjie Ruan wrote:
> Support for parallel secondary CPU bringup is already utilized by x86,
> MIPS, and RISC-V. This patch brings this capability to the arm64
> architecture.
>
> Introduce CONFIG_PARALLEL_SMT_PRIMARY_FIRST to avoid primary SMT threads
> to boot first constraint.
>
> And Add a 'cpu' parameter to update_cpu_boot_status() to allow updating the
> boot status at a per-CPU granularity during parallel bringup.
>
> Rework the global `secondary_data` accessed during early boot into
> a per-CPU array `cpu_boot_data` to allow secondary CPUs to boot
> in parallel.
>
> And reuse `__cpu_logical_map` array in the early boot code in head.S
> to resolve each secondary CPU's logical ID concurrently.
>
> Changes in v2:
> - Remove RFC.
> - Add Tested-by.
> - Fix AI review issues in [1].
> - Add arch_cpuhp_init_parallel_bringup() to check psci boot.
> - Reuse `__cpu_logical_map` instead of a new aray.
> - Defer rcutree_report_cpu_starting() until after
> check_local_cpu_capabilities() to prevent a potential control CPU
> deadlock if an early capability check fails.
> - Move the assembly in head.S to a macro called `mpidr_to_cpuid`.
> - Add `SECONDARY_DATA_SHIFT` for `lsl` to access `cpu_boot_data`.
> - Add sizeof(struct secondary_data) power of 2 assert check.
> - Expand testing with more data collected from real hardware.
>
> [1] https://sashiko.dev/#/patchset/20260611133809.3854977-1-ruanjinjie%40huawei.com
>
> Jinjie Ruan (4):
> cpu/hotplug: Introduce CONFIG_PARALLEL_SMT_PRIMARY_FIRST
> arm64: smp: Pass CPU ID to update_cpu_boot_status()
> arm64: smp: Defer RCU reporting until after local CPU capability
> checks
> arm64: Add HOTPLUG_PARALLEL support for secondary CPUs
>
> arch/Kconfig | 4 +++
> arch/arm64/Kconfig | 1 +
> arch/arm64/include/asm/smp.h | 17 ++++++++++---
> arch/arm64/kernel/asm-offsets.c | 4 +++
> arch/arm64/kernel/cpufeature.c | 22 ++++++++--------
> arch/arm64/kernel/head.S | 36 ++++++++++++++++++++++++++
> arch/arm64/kernel/smp.c | 45 ++++++++++++++++++++++++++++-----
> arch/arm64/mm/context.c | 4 +--
> arch/mips/Kconfig | 1 +
> arch/riscv/Kconfig | 1 +
> arch/x86/Kconfig | 1 +
> kernel/cpu.c | 6 ++++-
> 12 files changed, 119 insertions(+), 23 deletions(-)
>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply
* RE: [PATCH v2 17/28] drm/i915/dp_link_caps: Add helper to get common rate index
From: Kahola, Mika @ 2026-06-24 9:02 UTC (permalink / raw)
To: Deak, Imre, intel-gfx@lists.freedesktop.org,
intel-xe@lists.freedesktop.org
In-Reply-To: <20260616200849.3534628-18-imre.deak@intel.com>
> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of Imre Deak
> Sent: Tuesday, 16 June 2026 23.09
> To: intel-gfx@lists.freedesktop.org; intel-xe@lists.freedesktop.org
> Subject: [PATCH v2 17/28] drm/i915/dp_link_caps: Add helper to get common rate index
>
> Add intel_dp_link_caps_common_rate_idx() to look up supported link rates
> tracked by the link_caps module by rate. This prepares for tracking these
> capabilities internally within the link caps module.
>
Reviewed-by: Mika Kahola <mika.kahola@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_dp_link_caps.c | 9 +++++++++
> drivers/gpu/drm/i915/display/intel_dp_link_caps.h | 1 +
> drivers/gpu/drm/i915/display/intel_dp_link_training.c | 5 ++---
> drivers/gpu/drm/i915/display/intel_dp_test.c | 7 ++++---
> 4 files changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
> index 09b60a0cd6fbb..84d9636f4adb4 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
> @@ -61,6 +61,15 @@ int intel_dp_common_rate(struct intel_dp *intel_dp, int index)
> return intel_dp->common_rates[index];
> }
>
> +int intel_dp_link_caps_common_rate_idx(struct intel_dp_link_caps *link_caps, int rate)
> +{
> + struct intel_dp *intel_dp = link_caps->dp;
> +
> + return intel_dp_rate_index(intel_dp->common_rates,
> + intel_dp->num_common_rates,
> + rate);
> +}
> +
> /* Theoretical max between source and sink */
> int intel_dp_max_common_rate(struct intel_dp *intel_dp)
> {
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_caps.h b/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
> index 3413f6f760453..7d7d3d11ba3fe 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
> @@ -14,6 +14,7 @@ struct intel_dp_link_config;
> int intel_dp_common_len_rate_limit(const struct intel_dp *intel_dp,
> int max_rate);
> int intel_dp_common_rate(struct intel_dp *intel_dp, int index);
> +int intel_dp_link_caps_common_rate_idx(struct intel_dp_link_caps *link_caps, int rate);
> int intel_dp_max_common_rate(struct intel_dp *intel_dp);
> int intel_dp_link_caps_num_common_rates(struct intel_dp_link_caps *link_caps);
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> index 61ada34ab9c8e..ec9bd9b4c800b 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> @@ -1891,9 +1891,8 @@ static int reduce_link_rate(struct intel_dp *intel_dp, int current_rate)
> if (forced_params.rate)
> return -1;
>
> - rate_index = intel_dp_rate_index(intel_dp->common_rates,
> - intel_dp->num_common_rates,
> - current_rate);
> + rate_index = intel_dp_link_caps_common_rate_idx(link_caps,
> + current_rate);
>
> if (rate_index <= 0)
> return -1;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.c b/drivers/gpu/drm/i915/display/intel_dp_test.c
> index ba44769c9cfbe..da7632536dace 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_test.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_test.c
> @@ -14,6 +14,7 @@
> #include "intel_display_regs.h"
> #include "intel_display_types.h"
> #include "intel_dp.h"
> +#include "intel_dp_link_caps.h"
> #include "intel_dp_link_training.h"
> #include "intel_dp_mst.h"
> #include "intel_dp_test.h"
> @@ -32,6 +33,7 @@ void intel_dp_test_compute_config(struct intel_dp *intel_dp,
> struct intel_crtc_state *pipe_config,
> struct link_config_limits *limits)
> {
> + struct intel_dp_link_caps *link_caps = intel_dp->link.caps;
> struct intel_display *display = to_intel_display(intel_dp);
>
> /* For DP Compliance we override the computed bpp for the pipe */
> @@ -54,9 +56,8 @@ void intel_dp_test_compute_config(struct intel_dp *intel_dp,
> */
> if (intel_dp_link_params_valid(intel_dp, intel_dp->compliance.test_link_rate,
> intel_dp->compliance.test_lane_count)) {
> - index = intel_dp_rate_index(intel_dp->common_rates,
> - intel_dp->num_common_rates,
> - intel_dp->compliance.test_link_rate);
> + index = intel_dp_link_caps_common_rate_idx(link_caps,
> + intel_dp->compliance.test_link_rate);
> if (index >= 0) {
> limits->min_rate = intel_dp->compliance.test_link_rate;
> limits->max_rate = intel_dp->compliance.test_link_rate;
> --
> 2.49.1
^ permalink raw reply
* Re: [PATCH v2 0/4] arm64: Add HOTPLUG_PARALLEL support for secondary CPUs
From: Jinjie Ruan @ 2026-06-24 9:02 UTC (permalink / raw)
To: catalin.marinas, will, tsbogend, pjw, palmer, aou, alex, tglx,
mingo, bp, dave.hansen, hpa, peterz, kees, nathan, linusw,
jpoimboe, lukas.bulwahn, ryan.roberts, ojeda, maz, timothy.hayes,
lpieralisi, thuth, menglong8.dong, oupton, yeoreum.yun,
miko.lenczewski, broonie, kevin.brodsky, james.clark, tabba,
mrigendra.chaubey, arnd, anshuman.khandual, x86, linux-kernel,
linux-arm-kernel, linux-mips, linux-riscv, apatel, mhklinux
In-Reply-To: <20260618092444.1316336-1-ruanjinjie@huawei.com>
Please ignore this patchset, will update in v3.
On 6/18/2026 5:24 PM, Jinjie Ruan wrote:
> Support for parallel secondary CPU bringup is already utilized by x86,
> MIPS, and RISC-V. This patch brings this capability to the arm64
> architecture.
>
> Introduce CONFIG_PARALLEL_SMT_PRIMARY_FIRST to avoid primary SMT threads
> to boot first constraint.
>
> And Add a 'cpu' parameter to update_cpu_boot_status() to allow updating the
> boot status at a per-CPU granularity during parallel bringup.
>
> Rework the global `secondary_data` accessed during early boot into
> a per-CPU array `cpu_boot_data` to allow secondary CPUs to boot
> in parallel.
>
> And reuse `__cpu_logical_map` array in the early boot code in head.S
> to resolve each secondary CPU's logical ID concurrently.
>
> Changes in v2:
> - Remove RFC.
> - Add Tested-by.
> - Fix AI review issues in [1].
> - Add arch_cpuhp_init_parallel_bringup() to check psci boot.
> - Reuse `__cpu_logical_map` instead of a new aray.
> - Defer rcutree_report_cpu_starting() until after
> check_local_cpu_capabilities() to prevent a potential control CPU
> deadlock if an early capability check fails.
> - Move the assembly in head.S to a macro called `mpidr_to_cpuid`.
> - Add `SECONDARY_DATA_SHIFT` for `lsl` to access `cpu_boot_data`.
> - Add sizeof(struct secondary_data) power of 2 assert check.
> - Expand testing with more data collected from real hardware.
>
> [1] https://sashiko.dev/#/patchset/20260611133809.3854977-1-ruanjinjie%40huawei.com
>
> Jinjie Ruan (4):
> cpu/hotplug: Introduce CONFIG_PARALLEL_SMT_PRIMARY_FIRST
> arm64: smp: Pass CPU ID to update_cpu_boot_status()
> arm64: smp: Defer RCU reporting until after local CPU capability
> checks
> arm64: Add HOTPLUG_PARALLEL support for secondary CPUs
>
> arch/Kconfig | 4 +++
> arch/arm64/Kconfig | 1 +
> arch/arm64/include/asm/smp.h | 17 ++++++++++---
> arch/arm64/kernel/asm-offsets.c | 4 +++
> arch/arm64/kernel/cpufeature.c | 22 ++++++++--------
> arch/arm64/kernel/head.S | 36 ++++++++++++++++++++++++++
> arch/arm64/kernel/smp.c | 45 ++++++++++++++++++++++++++++-----
> arch/arm64/mm/context.c | 4 +--
> arch/mips/Kconfig | 1 +
> arch/riscv/Kconfig | 1 +
> arch/x86/Kconfig | 1 +
> kernel/cpu.c | 6 ++++-
> 12 files changed, 119 insertions(+), 23 deletions(-)
>
^ permalink raw reply
* Re: [PATCH 1/3] virtio-gpu-virgl: validate resource existence on ctx attach/detach
From: Akihiko Odaki @ 2026-06-24 9:01 UTC (permalink / raw)
To: Bin Guo, alex.bennee; +Cc: mst, dmitry.osipenko, qemu-devel
In-Reply-To: <32f6f23fb4880a4f1ec3056fde306332d54e442f.1782270919.git.guobin@linux.alibaba.com>
On 2026/06/24 14:55, Bin Guo wrote:
> The CTX_ATTACH_RESOURCE and CTX_DETACH_RESOURCE command handlers
> forwarded the guest-supplied resource_id directly to virglrenderer
> without verifying that the resource actually exists. A malicious or
> buggy guest could reference an invalid resource_id, potentially causing
> undefined behavior inside virglrenderer.
>
> Resolve the long-standing "TODO add security" comments by checking the
> resource against QEMU's own resource table (virtio_gpu_find_resource)
> before forwarding the request. This is consistent with how other
> command handlers in virtio-gpu.c validate resource references.
I think it is better to be checked inside virglrenderer. In general, the
timings/places of check and usage should be centralized to ensure that
the invariant required by usage is properly covered by the check and to
avoid time-of-check to time-of-use (ToCTToU) bugs. Since virglrenderer
uses the value, it should also check it.
Furthermore, checking resource_id is insufficient as it does not cover
another parameter, ctx_id, despite that the TODO comments are removed.
QEMU currently has no knowledge what ctx_id is valid, so it also
motivates having checks inside virglrenderer. The corresponding
functions of virglrenderer may be extended to have return values for
error reporting like other virglrenderer functions.
Regards,
Akihiko Odaki
>
> Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
> ---
> hw/display/virtio-gpu-virgl.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index 60c78af06a..b992ffc44e 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -743,6 +743,14 @@ static void virgl_cmd_ctx_attach_resource(VirtIOGPU *g,
> trace_virtio_gpu_cmd_ctx_res_attach(att_res.hdr.ctx_id,
> att_res.resource_id);
>
> + if (!virtio_gpu_find_resource(g, att_res.resource_id)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: invalid resource %d for ctx %d\n",
> + __func__, att_res.resource_id, att_res.hdr.ctx_id);
> + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> + return;
> + }
> +
> virgl_renderer_ctx_attach_resource(att_res.hdr.ctx_id, att_res.resource_id);
> }
>
> @@ -755,6 +763,14 @@ static void virgl_cmd_ctx_detach_resource(VirtIOGPU *g,
> trace_virtio_gpu_cmd_ctx_res_detach(det_res.hdr.ctx_id,
> det_res.resource_id);
>
> + if (!virtio_gpu_find_resource(g, det_res.resource_id)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "%s: invalid resource %d for ctx %d\n",
> + __func__, det_res.resource_id, det_res.hdr.ctx_id);
> + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
> + return;
> + }
> +
> virgl_renderer_ctx_detach_resource(det_res.hdr.ctx_id, det_res.resource_id);
> }
>
> @@ -1073,11 +1089,9 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
> virgl_cmd_resource_unref(g, cmd, &cmd_suspended);
> break;
> case VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE:
> - /* TODO add security */
> virgl_cmd_ctx_attach_resource(g, cmd);
> break;
> case VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE:
> - /* TODO add security */
> virgl_cmd_ctx_detach_resource(g, cmd);
> break;
> case VIRTIO_GPU_CMD_GET_CAPSET_INFO:
^ permalink raw reply
* Re: perf: Fix dangling cgroup pointer in cpuctx
From: Greg KH @ 2026-06-24 9:01 UTC (permalink / raw)
To: Wentao Guan
Cc: iklatzco, 00107082, patches, peterz, sashal, stable, yeoreum.yun
In-Reply-To: <20260624080310.2502480-1-guanwentao@uniontech.com>
On Wed, Jun 24, 2026 at 04:03:10PM +0800, Wentao Guan wrote:
> Hello,
>
> I noticed your backport missed - 'event->pending_disable = 1;',
> which different than upstream version, is that true?
I have no context here at all :(
^ permalink raw reply
* Re: Please apply 736b380e28d0 and eca856950f7c down to 6.1.y
From: Greg Kroah-Hartman @ 2026-06-24 9:00 UTC (permalink / raw)
To: Wongi Lee
Cc: stable, Sasha Levin, netdev, David Ahern, Ido Schimmel,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jungwoo Lee
In-Reply-To: <ajuR7rZYU943EG6p@DESKTOP-19IMU7U.localdomain>
On Wed, Jun 24, 2026 at 05:14:38PM +0900, Wongi Lee wrote:
> Hi,
>
> Could the following upstream commits be queued for the active stable
> trees?
>
> commit 736b380e28d0480c7bc3e022f1950f31fe53a7c5
> ("ipv6: account for fraggap on the paged allocation path")
I do not see that commit id in Linus's tree, are you sure it is correct?
> commit eca856950f7cb1a221e02b99d758409f2c5cec42
> ("ipv4: account for fraggap on the paged allocation path")
Same here, no id of that one in Linus's tree that I can see.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH v4 6/6] x86/resctrl: Add support for L3 occupancy monitoring via RMID MMIO read
From: Chen, Yu C @ 2026-06-24 9:00 UTC (permalink / raw)
To: Reinette Chatre
Cc: x86, linux-kernel, tglx, bp, mingo, dave.hansen, hpa, dave.martin,
james.morse, fenghuay, babu.moger, anil.keshavamurthy, tony.luck,
chen.yu
In-Reply-To: <1308bfd9-e2e8-4dc5-9847-fbb99f177477@intel.com>
Hi Reinette,
On 6/24/2026 12:48 AM, Reinette Chatre wrote:
> Hi Chenyu,
>
> On 6/22/26 10:00 PM, Chen, Yu C wrote:
>> Hi Reinette,
>>
>> On 6/23/2026 5:30 AM, Reinette Chatre wrote:
>>> Hi Chenyu,
>>>>>> diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
>>>>>> index 97c2f6bc7a5f..9b3b03279dd8 100644
>>>>>> --- a/arch/x86/include/asm/resctrl.h
>>>>>> +++ b/arch/x86/include/asm/resctrl.h
>>>>>> @@ -41,6 +41,8 @@ struct resctrl_pqr_state {
>>>>>> };
>>>>>> bool erdt_enabled(void);
>>>>>> +struct rdt_domain_hdr;
>>>>>> +int erdt_mon_read(struct rdt_domain_hdr *hdr, int ev_id, int rmid, u64 *val);
>>>>>> DECLARE_PER_CPU(struct resctrl_pqr_state, pqr_state);
>>>>>> diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
>>>>>> index 90730f0851fa..fe812f7190fc 100644
>>>>>> --- a/arch/x86/kernel/cpu/resctrl/core.c
>>>>>> +++ b/arch/x86/kernel/cpu/resctrl/core.c
>>>>>> @@ -965,7 +965,7 @@ static __init bool get_rdt_mon_resources(void)
>>>>>> bool ret = false;
>>>>>> if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) {
>>>>>> - resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, false, 0, NULL);
>>>>>> + resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID, erdt_enabled(), 0, NULL);
>>>>>> ret = true;
>>>>>> }
>>>>>> if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) {
>>>>>
>>>>> As mentioned in patch #1, when erdt_enabled() is true the enumeration still proceeds to
>>>>> enumerate the monitoring properties via CPUID to discover the number of RMIDs that the
>>>>> *MSR* supports and use it as the maximum RMID (and thus the maximum number of registers)
>>>>> that MMIO supports?
>>>>>
>>>>
>>>> OK, will switch to the maximum RMID exposed by ACPI table, if erdt_enabled() is true.
>>>
>>> I believe the issue is larger than just the RMID enumeration. The CPUID and ACPI enumeration
>>> appears to be fully intertwined. Taking a closer look at what above code does:
>>> it checks *CPUID* whether CMT is enabled and then enables the LLC occupancy event to blindly use
>>> MMIO if ERDT is enabled, irrespective of whether the ERDT tables include a cache monitoring table
>>> or not. How is it guaranteed that if ERDT is enabled that there is a cache monitoring table?
>>> Should it not be the existence of the ACPI cache monitoring table and its properties that
>>> determines whether the LLC occupancy counter using MMIO registers should be enabled?
>>>
>>
>> I see. How about replacing erdt_enabled() with fine-grained helper functions such as
>> erdt_has_cmrc(), erdt_has_mmrc(), and erdt_has_marc()? The latter two will be added
>> later for region-aware MBM/MBA. CMRC, MMRC and MARC are not guaranteed to coexist,
>> so splitting them into separate helpers would offer finer control.
> I am concerned where this is headed since it looks to me as though the plan is to
> sprinkle these finer grained checks throughout resctrl.
The erdt_has_* helper functions would ideally live under
arch/x86/kernel/cpu/resctrl/
rather than the generic fs/resctrl directory, as architecture-specific
code in the
former path is allow to see erdt logic I suppose? That said, since there
are a large
number of such routines, introduce a dedicated helper to handle this
uniformly would
be better(using arch_priv)
> To me this sounds complicated
> and error prone. Consider that resctrl_enable_mon_event() has an arch_priv parameter. To me
> this seems to be the appropriate place for the architecture to give itself the needed
> information about how to read the event.
>
OK, if I understand correctly, we can use the following logic to hide
erdt from monitor read:
/*
* helper to get the erdt's monitor arch_priv,
* defined in erdt.c, NULL in other place.
*
* caller doesn't know about CMRC
*/
void *get_evt_priv(enum resctrl_event_id eventid)
{
if (!erdt_enabled())
return NULL;
switch (eventid) {
case QOS_L3_OCCUP_EVENT_ID:
return cmrc_priv_valid ? &cmrc_priv : NULL;
default:
return NULL;
}
}
arch/x86/kernel/cpu/resctrl/core.c
get_rdt_mon_resources():
if (rdt_cpu_has(X86_FEATURE_CQM_OCCUP_LLC)) {
void *priv = get_evt_priv(QOS_L3_OCCUP_EVENT_ID);
resctrl_enable_mon_event(QOS_L3_OCCUP_EVENT_ID,
priv != NULL, 0, priv);
}
arch/x86/kernel/cpu/resctrl/monitor.c
resctrl_arch_rmid_read():
if (arch_priv)
return erdt_mon_read(hdr, eventid, rmid, val);
return arch_l3_read_event(hdr, rmid, eventid, val, r);
So in this way, there is no event-type checks in the read
path. Adding MMRC later only extends the switch in get_evt_priv().
thanks,
Chenyu
^ permalink raw reply
* [BUG] KFENCE: use-after-free read in udp_tunnel_nic_device_sync_work
From: Yue Sun @ 2026-06-24 9:01 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: netdev, linux-kernel, syzkaller
Hello,
I hit a reproducible use-after-free in the UDP tunnel NIC offload work item.
The original local crash was reported by KFENCE as:
KFENCE: use-after-free read in udp_tunnel_nic_device_sync_work
On current mainline, the C reproducer below triggers the same lifetime bug,
reported by KASAN before KFENCE samples the object:
BUG: KASAN: slab-use-after-free in __mutex_lock
Workqueue: udp_tunnel_nic udp_tunnel_nic_device_sync_work
Tested kernel:
840ef6c78e6a ("Merge tag 'nfs-for-7.2-1' of git://git.linux-nfs.org/projects/anna/linux-nfs")
Linux 7.1.0-11240-g840ef6c78e6a #31 SMP PREEMPT_DYNAMIC
Related syzbot reports:
https://syzkaller.appspot.com/bug?id=8d8fd27ae4339074afe3f456be73b2030d795256
The dashboard currently marks it as invalid, but the same issue is still
reproducible for me on current mainline with the C reproducer pasted below.
Crash stack from the latest C reproducer run:
[ 131.757233][ T12] BUG: KASAN: slab-use-after-free in __mutex_lock+0x16d0/0x1d80
[ 131.759738][ T12] Read of size 8 at addr ff11000065dcd2a8 by task kworker/u16:0/12
[ 131.762204][ T12]
[ 131.762956][ T12] CPU: 2 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 7.1.0-11240-g840ef6c78e6a #31 PREEMPT(full)
[ 131.762997][ T12] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[ 131.763020][ T12] Workqueue: udp_tunnel_nic udp_tunnel_nic_device_sync_work
[ 131.763064][ T12] Call Trace:
[ 131.763076][ T12] <TASK>
[ 131.763089][ T12] dump_stack_lvl+0x116/0x1b0
[ 131.763136][ T12] print_report+0xf1/0x5c0
[ 131.763178][ T12] ? __virt_addr_valid+0x238/0x420
[ 131.763214][ T12] ? __mutex_lock+0x16d0/0x1d80
[ 131.763264][ T12] kasan_report+0xca/0x100
[ 131.763301][ T12] ? __mutex_lock+0x16d0/0x1d80
[ 131.763345][ T12] __mutex_lock+0x16d0/0x1d80
[ 131.763383][ T12] ? udp_tunnel_nic_device_sync_work+0x32/0x9c0
[ 131.763438][ T12] ? __pfx___mutex_lock+0x10/0x10
[ 131.763487][ T12] ? debug_object_deactivate+0x213/0x390
[ 131.763551][ T12] ? udp_tunnel_nic_device_sync_work+0x32/0x9c0
[ 131.763587][ T12] udp_tunnel_nic_device_sync_work+0x32/0x9c0
[ 131.763633][ T12] process_one_work+0x9de/0x1bf0
[ 131.763670][ T12] ? __pfx_udp_tunnel_nic_device_sync_work+0x10/0x10
[ 131.763710][ T12] ? __pfx_process_one_work+0x10/0x10
[ 131.763747][ T12] ? __pfx_udp_tunnel_nic_device_sync_work+0x10/0x10
[ 131.763787][ T12] worker_thread+0x693/0xeb0
[ 131.763823][ T12] ? __pfx_worker_thread+0x10/0x10
[ 131.763855][ T12] kthread+0x38d/0x4a0
[ 131.763903][ T12] ? __pfx_kthread+0x10/0x10
[ 131.763953][ T12] ret_from_fork+0xb09/0xdb0
[ 131.763997][ T12] ? __pfx_ret_from_fork+0x10/0x10
[ 131.764037][ T12] ? __pfx_kthread+0x10/0x10
[ 131.764082][ T12] ? kthread_affine_node+0x210/0x230
[ 131.764131][ T12] ? __switch_to+0x7a7/0x10e0
[ 131.764174][ T12] ? __pfx_kthread+0x10/0x10
[ 131.764221][ T12] ret_from_fork_asm+0x1a/0x30
[ 131.764269][ T12] </TASK>
[ 131.764280][ T12]
[ 131.810468][ T12] Allocated by task 10356:
[ 131.811305][ T12] kasan_save_stack+0x24/0x50
[ 131.812187][ T12] kasan_save_track+0x14/0x30
[ 131.813069][ T12] __kasan_kmalloc+0xaa/0xb0
[ 131.813959][ T12] __kmalloc_noprof+0x345/0x7f0
[ 131.814882][ T12] udp_tunnel_nic_netdevice_event+0x1285/0x1de0
[ 131.816061][ T12] notifier_call_chain+0xbd/0x430
[ 131.817014][ T12] call_netdevice_notifiers_info+0xbe/0x110
[ 131.819862][ T12] register_netdevice+0x197c/0x2440
[ 131.820868][ T12] nsim_create+0xcd5/0x14b0
[ 131.821733][ T12] __nsim_dev_port_add+0x3c2/0x900
[ 131.822701][ T12] nsim_dev_reload_up+0x42c/0x6a0
[ 131.823584][ T12] devlink_reload+0x2e3/0x7b0
[ 131.824421][ T12] devlink_nl_reload_doit+0x541/0x1160
[ 131.825385][ T12] genl_family_rcv_msg_doit+0x1ff/0x2f0
[ 131.826358][ T12] genl_rcv_msg+0x532/0x7e0
[ 131.827159][ T12] netlink_rcv_skb+0x147/0x430
[ 131.828017][ T12] genl_rcv+0x28/0x40
[ 131.828724][ T12] netlink_unicast+0x58d/0x850
[ 131.829582][ T12] netlink_sendmsg+0x88d/0xd90
[ 131.830439][ T12] ____sys_sendmsg+0xa27/0xb90
[ 131.831286][ T12] ___sys_sendmsg+0x11c/0x1b0
[ 131.832106][ T12] __sys_sendmsg+0x142/0x1f0
[ 131.832927][ T12] do_syscall_64+0x11f/0x860
[ 131.833745][ T12] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 131.834791][ T12]
[ 131.835206][ T12] Freed by task 10421:
[ 131.835916][ T12] kasan_save_stack+0x24/0x50
[ 131.836742][ T12] kasan_save_track+0x14/0x30
[ 131.837564][ T12] kasan_save_free_info+0x3b/0x60
[ 131.838465][ T12] __kasan_slab_free+0x61/0x80
[ 131.839314][ T12] kfree+0x2ca/0x6d0
[ 131.840008][ T12] udp_tunnel_nic_netdevice_event+0xc24/0x1de0
[ 131.841080][ T12] notifier_call_chain+0xbd/0x430
[ 131.841981][ T12] call_netdevice_notifiers_info+0xbe/0x110
[ 131.843022][ T12] unregister_netdevice_many_notify+0xbab/0x2130
[ 131.844129][ T12] unregister_netdevice_queue+0x305/0x3c0
[ 131.845132][ T12] nsim_destroy+0x231/0x980
[ 131.845960][ T12] __nsim_dev_port_del+0x197/0x2c0
[ 131.846860][ T12] nsim_dev_reload_destroy+0x105/0x490
[ 131.847823][ T12] nsim_dev_reload_down+0x67/0xd0
[ 131.848707][ T12] devlink_reload+0x197/0x7b0
[ 131.849545][ T12] devlink_nl_reload_doit+0x541/0x1160
[ 131.850517][ T12] genl_family_rcv_msg_doit+0x1ff/0x2f0
[ 131.851489][ T12] genl_rcv_msg+0x532/0x7e0
[ 131.852282][ T12] netlink_rcv_skb+0x147/0x430
[ 131.853130][ T12] genl_rcv+0x28/0x40
[ 131.853836][ T12] netlink_unicast+0x58d/0x850
[ 131.854689][ T12] netlink_sendmsg+0x88d/0xd90
[ 131.855497][ T12] ____sys_sendmsg+0xa27/0xb90
[ 131.856293][ T12] ___sys_sendmsg+0x11c/0x1b0
[ 131.857067][ T12] __sys_sendmsg+0x142/0x1f0
[ 131.857826][ T12] do_syscall_64+0x11f/0x860
[ 131.858605][ T12] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 131.859579][ T12]
[ 131.859971][ T12] Last potentially related work creation:
[ 131.860910][ T12] kasan_save_stack+0x24/0x50
[ 131.861694][ T12] kasan_record_aux_stack+0xa7/0xc0
[ 131.862563][ T12] insert_work+0x36/0x230
[ 131.863276][ T12] __queue_work+0x474/0x12a0
[ 131.864038][ T12] queue_work_on+0x11c/0x140
[ 131.864800][ T12] __udp_tunnel_nic_del_port+0x2a5/0x350
[ 131.865733][ T12] udp_tunnel_notify_del_rx_port+0x228/0x410
[ 131.866698][ T12] __geneve_sock_release.part.0+0x13b/0x1d0
[ 131.867583][ T12] geneve_sock_release+0x165/0x2c0
[ 131.868346][ T12] geneve_stop+0x19c/0x200
[ 131.869001][ T12] __dev_close_many+0x350/0x720
[ 131.869733][ T12] __dev_change_flags+0x301/0x860
[ 131.870474][ T12] netif_change_flags+0x8e/0x170
[ 131.871208][ T12] do_setlink.constprop.0+0xac0/0x3f80
[ 131.872011][ T12] rtnl_newlink+0x17e7/0x1f30
[ 131.872711][ T12] rtnetlink_rcv_msg+0x9e8/0xfa0
[ 131.873455][ T12] netlink_rcv_skb+0x147/0x430
[ 131.874207][ T12] netlink_unicast+0x58d/0x850
[ 131.874959][ T12] netlink_sendmsg+0x88d/0xd90
[ 131.875685][ T12] ____sys_sendmsg+0xa27/0xb90
[ 131.876406][ T12] ___sys_sendmsg+0x11c/0x1b0
[ 131.877102][ T12] __sys_sendmsg+0x142/0x1f0
[ 131.877803][ T12] do_syscall_64+0x11f/0x860
[ 131.878505][ T12] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 131.879297][ T12]
[ 131.879611][ T12] Second to last potentially related work creation:
[ 131.880480][ T12] kasan_save_stack+0x24/0x50
[ 131.881112][ T12] kasan_record_aux_stack+0xa7/0xc0
[ 131.881818][ T12] insert_work+0x36/0x230
[ 131.882403][ T12] __queue_work+0x474/0x12a0
[ 131.883019][ T12] queue_work_on+0x11c/0x140
[ 131.883634][ T12] __udp_tunnel_nic_add_port+0x6e4/0xd90
[ 131.884385][ T12] udp_tunnel_notify_add_rx_port+0x228/0x410
[ 131.885199][ T12] geneve_sock_add+0x7a3/0xb60
[ 131.885844][ T12] geneve_open+0xde/0x1d0
[ 131.886435][ T12] __dev_open+0x3b8/0x900
[ 131.887017][ T12] __dev_change_flags+0x58f/0x860
[ 131.887692][ T12] netif_change_flags+0x8e/0x170
[ 131.888389][ T12] do_setlink.constprop.0+0xac0/0x3f80
[ 131.889130][ T12] rtnl_newlink+0x17e7/0x1f30
[ 131.889774][ T12] rtnetlink_rcv_msg+0x9e8/0xfa0
[ 131.890455][ T12] netlink_rcv_skb+0x147/0x430
[ 131.891065][ T12] netlink_unicast+0x58d/0x850
[ 131.891654][ T12] netlink_sendmsg+0x88d/0xd90
[ 131.892251][ T12] ____sys_sendmsg+0xa27/0xb90
[ 131.892837][ T12] ___sys_sendmsg+0x11c/0x1b0
[ 131.893412][ T12] __sys_sendmsg+0x142/0x1f0
[ 131.893988][ T12] do_syscall_64+0x11f/0x860
[ 131.894559][ T12] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 131.895275][ T12]
[ 131.895564][ T12] The buggy address belongs to the object at ff11000065dcd200
[ 131.895564][ T12] which belongs to the cache kmalloc-256 of size 256
[ 131.897253][ T12] The buggy address is located 168 bytes inside of
[ 131.897253][ T12] freed 256-byte region [ff11000065dcd200, ff11000065dcd300)
[ 131.898932][ T12]
[ 131.899228][ T12] The buggy address belongs to the physical page:
[ 131.900013][ T12] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x65dcc
[ 131.901089][ T12] head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 131.902125][ T12] flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
[ 131.903017][ T12] page_type: f5(slab)
[ 131.903477][ T12] raw: 00fff00000000040 ff11000100038b40 dead000000000100 dead000000000122
[ 131.904457][ T12] raw: 0000000000000000 0000000800100010 00000000f5000000 0000000000000000
[ 131.905422][ T12] head: 00fff00000000040 ff11000100038b40 dead000000000100 dead000000000122
[ 131.906405][ T12] head: 0000000000000000 0000000800100010 00000000f5000000 0000000000000000
[ 131.907388][ T12] head: 00fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff
[ 131.908365][ T12] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002
[ 131.909334][ T12] page dumped because: kasan: bad access detected
[ 131.910076][ T12] page_owner tracks the page as allocated
[ 131.910720][ T12] page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9905, tgid 9901 (repro), ts 81743543441, free_ts 81726980842
[ 131.913040][ T12] post_alloc_hook+0xff/0x130
[ 131.913579][ T12] get_page_from_freelist+0xe82/0x2bf0
[ 131.914216][ T12] __alloc_frozen_pages_noprof+0x27b/0x2a00
[ 131.914849][ T12] new_slab+0xad/0x610
[ 131.915190][ T12] refill_objects+0x10e/0x3d0
[ 131.915587][ T12] __pcs_replace_empty_main+0x352/0x670
[ 131.916050][ T12] __kmalloc_noprof+0x65e/0x7f0
[ 131.916458][ T12] ops_init+0x77/0x5f0
[ 131.916799][ T12] setup_net+0x11a/0x3a0
[ 131.917155][ T12] copy_net_ns+0x351/0x7c0
[ 131.917530][ T12] create_new_namespaces+0x3f6/0xac0
[ 131.917984][ T12] copy_namespaces+0x45c/0x580
[ 131.918389][ T12] copy_process+0x3687/0x7d40
[ 131.918788][ T12] kernel_clone+0x1f6/0x910
[ 131.919183][ T12] __do_sys_clone+0xce/0x120
[ 131.919575][ T12] do_syscall_64+0x11f/0x860
[ 131.919969][ T12] page last free pid 9905 tgid 9901 stack trace:
[ 131.920496][ T12] __free_frozen_pages+0x74d/0x1110
[ 131.920930][ T12] qlist_free_all+0x4c/0xf0
[ 131.921327][ T12] kasan_quarantine_reduce+0x195/0x1e0
[ 131.921791][ T12] __kasan_slab_alloc+0x67/0x90
[ 131.922202][ T12] kmem_cache_alloc_noprof+0x244/0x690
[ 131.922665][ T12] security_inode_alloc+0x3e/0x2d0
[ 131.923099][ T12] inode_init_always_gfp+0xc77/0xfb0
[ 131.923562][ T12] alloc_inode+0x8e/0x250
[ 131.923930][ T12] new_inode+0x22/0x1d0
[ 131.924284][ T12] __debugfs_create_file+0x10b/0x540
[ 131.924737][ T12] debugfs_create_file_full+0x41/0x60
[ 131.925189][ T12] ref_tracker_dir_debugfs+0x18c/0x2e0
[ 131.925658][ T12] alloc_netdev_mqs+0x31f/0x1600
[ 131.926078][ T12] ip6_tnl_init_net+0x12f/0x4c0
[ 131.926491][ T12] ops_init+0x1e2/0x5f0
[ 131.926843][ T12] setup_net+0x11a/0x3a0
[ 131.927201][ T12]
[ 131.927399][ T12] Memory state around the buggy address:
[ 131.927873][ T12] ff11000065dcd180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 131.928542][ T12] ff11000065dcd200: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 131.929231][ T12] >ff11000065dcd280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 131.929902][ T12] ^
[ 131.930375][ T12] ff11000065dcd300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 131.931050][ T12] ff11000065dcd380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 131.931723][ T12] ==================================================================
[ 131.932651][ T12] Kernel panic - not syncing: KASAN: panic_on_warn set ...
[ 131.933267][ T12] CPU: 2 UID: 0 PID: 12 Comm: kworker/u16:0 Not tainted 7.1.0-11240-g840ef6c78e6a #31 PREEMPT(full)
[ 131.934181][ T12] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[ 131.934965][ T12] Workqueue: udp_tunnel_nic udp_tunnel_nic_device_sync_work
[ 131.935585][ T12] Call Trace:
[ 131.935865][ T12] <TASK>
The reproducer creates netdevsim/geneve devices and drives a devlink reload
while UDP tunnel offload notifications are being queued. A queued
udp_tunnel_nic_device_sync_work item later runs with its embedded work_struct
inside struct udp_tunnel_nic, but that struct has already been freed from the
NETDEV_UNREGISTER path. The first dereference in the worker is the mutex lock:
udp_tunnel_nic_device_sync_work()
rtnl_lock();
mutex_lock(&utn->lock);
KASAN reports the read from the freed object at that mutex access.
Possible root cause analysis:
The lifetime of struct udp_tunnel_nic appears to be guarded only by the
utn->work_pending flag, but that flag is not a safe lifetime barrier for the
queued work:
udp_tunnel_nic_device_sync()
queue_work(udp_tunnel_nic_workqueue, &utn->work);
utn->work_pending = 1;
udp_tunnel_nic_unregister()
udp_tunnel_nic_flush(dev, utn);
udp_tunnel_nic_unlock(dev);
if (utn->work_pending)
return;
udp_tunnel_nic_free(utn);
The work is queued before work_pending is set, so unregister can observe
work_pending == 0 and free utn while the work is already queued or starting.
Also, work_pending is only a flag in the object being protected; it is not a
reference, cancel_work_sync(), or flush_work() style guarantee that the worker
no longer owns or can dereference the containing object. Once udp_tunnel_nic_free()
runs, the embedded work item can still call container_of(work, struct
udp_tunnel_nic, work) and dereference the freed utn, which matches the
alloc/free/use stacks above.
A fix should make unregister synchronize with the embedded work or otherwise
hold a real lifetime reference while the work is queued/running. In particular,
freeing utn based solely on work_pending looks racy.
If you have any questions, please let me know.
Best regards,
Yue
Build/run:
gcc -pthread -static -O2 repro.c -o repro
./repro
C reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <linux/capability.h>
#include <linux/futex.h>
#include <linux/genetlink.h>
#include <linux/if_addr.h>
#include <linux/if_ether.h>
#include <linux/if_link.h>
#include <linux/if_tun.h>
#include <linux/in6.h>
#include <linux/ip.h>
#include <linux/neighbour.h>
#include <linux/net.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/tcp.h>
#include <linux/veth.h>
static unsigned long long procid;
static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}
static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}
static void thread_start(void* (*fn)(void*), void* arg)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}
#define BITMASK(bf_off,bf_len) (((1ull << (bf_len)) - 1) << (bf_off))
#define STORE_BY_BITMASK(type,htobe,addr,val,bf_off,bf_len) *(type*)(addr) = htobe((htobe(*(type*)(addr)) & ~BITMASK((bf_off), (bf_len))) | (((type)(val) << (bf_off)) & BITMASK((bf_off), (bf_len))))
typedef struct {
int state;
} event_t;
static void event_init(event_t* ev)
{
ev->state = 0;
}
static void event_reset(event_t* ev)
{
ev->state = 0;
}
static void event_set(event_t* ev)
{
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}
static void event_wait(event_t* ev)
{
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}
static int event_isset(event_t* ev)
{
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}
static int event_timedwait(event_t* ev, uint64_t timeout)
{
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}
static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
int err = errno;
close(fd);
errno = err;
return false;
}
close(fd);
return true;
}
struct nlmsg {
char* pos;
int nesting;
struct nlattr* nested[8];
char buf[4096];
};
static void netlink_init(struct nlmsg* nlmsg, int typ, int flags,
const void* data, int size)
{
memset(nlmsg, 0, sizeof(*nlmsg));
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
hdr->nlmsg_type = typ;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
memcpy(hdr + 1, data, size);
nlmsg->pos = (char*)(hdr + 1) + NLMSG_ALIGN(size);
}
static void netlink_attr(struct nlmsg* nlmsg, int typ,
const void* data, int size)
{
struct nlattr* attr = (struct nlattr*)nlmsg->pos;
attr->nla_len = sizeof(*attr) + size;
attr->nla_type = typ;
if (size > 0)
memcpy(attr + 1, data, size);
nlmsg->pos += NLMSG_ALIGN(attr->nla_len);
}
static void netlink_nest(struct nlmsg* nlmsg, int typ)
{
struct nlattr* attr = (struct nlattr*)nlmsg->pos;
attr->nla_type = typ;
nlmsg->pos += sizeof(*attr);
nlmsg->nested[nlmsg->nesting++] = attr;
}
static void netlink_done(struct nlmsg* nlmsg)
{
struct nlattr* attr = nlmsg->nested[--nlmsg->nesting];
attr->nla_len = nlmsg->pos - (char*)attr;
}
static int netlink_send_ext(struct nlmsg* nlmsg, int sock,
uint16_t reply_type, int* reply_len, bool dofail)
{
if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting)
exit(1);
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
hdr->nlmsg_len = nlmsg->pos - nlmsg->buf;
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr));
if (n != (ssize_t)hdr->nlmsg_len) {
if (dofail)
exit(1);
return -1;
}
n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
if (reply_len)
*reply_len = 0;
if (n < 0) {
if (dofail)
exit(1);
return -1;
}
if (n < (ssize_t)sizeof(struct nlmsghdr)) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
if (hdr->nlmsg_type == NLMSG_DONE)
return 0;
if (reply_len && hdr->nlmsg_type == reply_type) {
*reply_len = n;
return 0;
}
if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
if (hdr->nlmsg_type != NLMSG_ERROR) {
errno = EINVAL;
if (dofail)
exit(1);
return -1;
}
errno = -((struct nlmsgerr*)(hdr + 1))->error;
return -errno;
}
static int netlink_send(struct nlmsg* nlmsg, int sock)
{
return netlink_send_ext(nlmsg, sock, 0, NULL, true);
}
static int netlink_query_family_id(struct nlmsg* nlmsg, int sock, const char* family_name, bool dofail)
{
struct genlmsghdr genlhdr;
memset(&genlhdr, 0, sizeof(genlhdr));
genlhdr.cmd = CTRL_CMD_GETFAMILY;
netlink_init(nlmsg, GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr));
netlink_attr(nlmsg, CTRL_ATTR_FAMILY_NAME, family_name, strnlen(family_name, GENL_NAMSIZ - 1) + 1);
int n = 0;
int err = netlink_send_ext(nlmsg, sock, GENL_ID_CTRL, &n, dofail);
if (err < 0) {
return -1;
}
uint16_t id = 0;
struct nlattr* attr = (struct nlattr*)(nlmsg->buf + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr)));
for (; (char*)attr < nlmsg->buf + n; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
if (attr->nla_type == CTRL_ATTR_FAMILY_ID) {
id = *(uint16_t*)(attr + 1);
break;
}
}
if (!id) {
errno = EINVAL;
return -1;
}
recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
return id;
}
static int netlink_next_msg(struct nlmsg* nlmsg, unsigned int offset,
unsigned int total_len)
{
struct nlmsghdr* hdr = (struct nlmsghdr*)(nlmsg->buf + offset);
if (offset == total_len || offset + hdr->nlmsg_len > total_len)
return -1;
return hdr->nlmsg_len;
}
static unsigned int queue_count = 2;
static void netlink_add_device_impl(struct nlmsg* nlmsg, const char* type,
const char* name, bool up)
{
struct ifinfomsg hdr;
memset(&hdr, 0, sizeof(hdr));
if (up)
hdr.ifi_flags = hdr.ifi_change = IFF_UP;
netlink_init(nlmsg, RTM_NEWLINK, NLM_F_EXCL | NLM_F_CREATE, &hdr, sizeof(hdr));
if (name)
netlink_attr(nlmsg, IFLA_IFNAME, name, strlen(name));
netlink_attr(nlmsg, IFLA_NUM_TX_QUEUES, &queue_count, sizeof(queue_count));
netlink_attr(nlmsg, IFLA_NUM_RX_QUEUES, &queue_count, sizeof(queue_count));
netlink_nest(nlmsg, IFLA_LINKINFO);
netlink_attr(nlmsg, IFLA_INFO_KIND, type, strlen(type));
}
static void netlink_add_device(struct nlmsg* nlmsg, int sock, const char* type,
const char* name)
{
netlink_add_device_impl(nlmsg, type, name, false);
netlink_done(nlmsg);
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static void netlink_add_veth(struct nlmsg* nlmsg, int sock, const char* name,
const char* peer)
{
netlink_add_device_impl(nlmsg, "veth", name, false);
netlink_nest(nlmsg, IFLA_INFO_DATA);
netlink_nest(nlmsg, VETH_INFO_PEER);
nlmsg->pos += sizeof(struct ifinfomsg);
netlink_attr(nlmsg, IFLA_IFNAME, peer, strlen(peer));
netlink_attr(nlmsg, IFLA_NUM_TX_QUEUES, &queue_count, sizeof(queue_count));
netlink_attr(nlmsg, IFLA_NUM_RX_QUEUES, &queue_count, sizeof(queue_count));
netlink_done(nlmsg);
netlink_done(nlmsg);
netlink_done(nlmsg);
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static void netlink_add_xfrm(struct nlmsg* nlmsg, int sock, const char* name)
{
netlink_add_device_impl(nlmsg, "xfrm", name, true);
netlink_nest(nlmsg, IFLA_INFO_DATA);
int if_id = 1;
netlink_attr(nlmsg, 2, &if_id, sizeof(if_id));
netlink_done(nlmsg);
netlink_done(nlmsg);
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static void netlink_add_hsr(struct nlmsg* nlmsg, int sock, const char* name,
const char* slave1, const char* slave2)
{
netlink_add_device_impl(nlmsg, "hsr", name, false);
netlink_nest(nlmsg, IFLA_INFO_DATA);
int ifindex1 = if_nametoindex(slave1);
netlink_attr(nlmsg, IFLA_HSR_SLAVE1, &ifindex1, sizeof(ifindex1));
int ifindex2 = if_nametoindex(slave2);
netlink_attr(nlmsg, IFLA_HSR_SLAVE2, &ifindex2, sizeof(ifindex2));
netlink_done(nlmsg);
netlink_done(nlmsg);
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static void netlink_add_linked(struct nlmsg* nlmsg, int sock, const char* type, const char* name, const char* link)
{
netlink_add_device_impl(nlmsg, type, name, false);
netlink_done(nlmsg);
int ifindex = if_nametoindex(link);
netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static void netlink_add_vlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16_t id, uint16_t proto)
{
netlink_add_device_impl(nlmsg, "vlan", name, false);
netlink_nest(nlmsg, IFLA_INFO_DATA);
netlink_attr(nlmsg, IFLA_VLAN_ID, &id, sizeof(id));
netlink_attr(nlmsg, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto));
netlink_done(nlmsg);
netlink_done(nlmsg);
int ifindex = if_nametoindex(link);
netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static void netlink_add_macvlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link)
{
netlink_add_device_impl(nlmsg, "macvlan", name, false);
netlink_nest(nlmsg, IFLA_INFO_DATA);
uint32_t mode = MACVLAN_MODE_BRIDGE;
netlink_attr(nlmsg, IFLA_MACVLAN_MODE, &mode, sizeof(mode));
netlink_done(nlmsg);
netlink_done(nlmsg);
int ifindex = if_nametoindex(link);
netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static void netlink_add_geneve(struct nlmsg* nlmsg, int sock, const char* name, uint32_t vni, struct in_addr* addr4, struct in6_addr* addr6)
{
netlink_add_device_impl(nlmsg, "geneve", name, false);
netlink_nest(nlmsg, IFLA_INFO_DATA);
netlink_attr(nlmsg, IFLA_GENEVE_ID, &vni, sizeof(vni));
if (addr4)
netlink_attr(nlmsg, IFLA_GENEVE_REMOTE, addr4, sizeof(*addr4));
if (addr6)
netlink_attr(nlmsg, IFLA_GENEVE_REMOTE6, addr6, sizeof(*addr6));
netlink_done(nlmsg);
netlink_done(nlmsg);
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
#define IFLA_IPVLAN_FLAGS 2
#define IPVLAN_MODE_L3S 2
#undef IPVLAN_F_VEPA
#define IPVLAN_F_VEPA 2
static void netlink_add_ipvlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16_t mode, uint16_t flags)
{
netlink_add_device_impl(nlmsg, "ipvlan", name, false);
netlink_nest(nlmsg, IFLA_INFO_DATA);
netlink_attr(nlmsg, IFLA_IPVLAN_MODE, &mode, sizeof(mode));
netlink_attr(nlmsg, IFLA_IPVLAN_FLAGS, &flags, sizeof(flags));
netlink_done(nlmsg);
netlink_done(nlmsg);
int ifindex = if_nametoindex(link);
netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static void netlink_device_change(struct nlmsg* nlmsg, int sock, const char* name, bool up,
const char* master, const void* mac, int macsize,
const char* new_name)
{
struct ifinfomsg hdr;
memset(&hdr, 0, sizeof(hdr));
if (up)
hdr.ifi_flags = hdr.ifi_change = IFF_UP;
hdr.ifi_index = if_nametoindex(name);
netlink_init(nlmsg, RTM_NEWLINK, 0, &hdr, sizeof(hdr));
if (new_name)
netlink_attr(nlmsg, IFLA_IFNAME, new_name, strlen(new_name));
if (master) {
int ifindex = if_nametoindex(master);
netlink_attr(nlmsg, IFLA_MASTER, &ifindex, sizeof(ifindex));
}
if (macsize)
netlink_attr(nlmsg, IFLA_ADDRESS, mac, macsize);
int err = netlink_send(nlmsg, sock);
if (err < 0) {
}
}
static int netlink_add_addr(struct nlmsg* nlmsg, int sock, const char* dev,
const void* addr, int addrsize)
{
struct ifaddrmsg hdr;
memset(&hdr, 0, sizeof(hdr));
hdr.ifa_family = addrsize == 4 ? AF_INET : AF_INET6;
hdr.ifa_prefixlen = addrsize == 4 ? 24 : 120;
hdr.ifa_scope = RT_SCOPE_UNIVERSE;
hdr.ifa_index = if_nametoindex(dev);
netlink_init(nlmsg, RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, &hdr, sizeof(hdr));
netlink_attr(nlmsg, IFA_LOCAL, addr, addrsize);
netlink_attr(nlmsg, IFA_ADDRESS, addr, addrsize);
return netlink_send(nlmsg, sock);
}
static void netlink_add_addr4(struct nlmsg* nlmsg, int sock,
const char* dev, const char* addr)
{
struct in_addr in_addr;
inet_pton(AF_INET, addr, &in_addr);
int err = netlink_add_addr(nlmsg, sock, dev, &in_addr, sizeof(in_addr));
if (err < 0) {
}
}
static void netlink_add_addr6(struct nlmsg* nlmsg, int sock,
const char* dev, const char* addr)
{
struct in6_addr in6_addr;
inet_pton(AF_INET6, addr, &in6_addr);
int err = netlink_add_addr(nlmsg, sock, dev, &in6_addr, sizeof(in6_addr));
if (err < 0) {
}
}
static struct nlmsg nlmsg;
#define DEVLINK_FAMILY_NAME "devlink"
#define DEVLINK_CMD_PORT_GET 5
#define DEVLINK_ATTR_BUS_NAME 1
#define DEVLINK_ATTR_DEV_NAME 2
#define DEVLINK_ATTR_NETDEV_NAME 7
static struct nlmsg nlmsg2;
static void initialize_devlink_ports(const char* bus_name, const char* dev_name,
const char* netdev_prefix)
{
struct genlmsghdr genlhdr;
int len, total_len, id, err, offset;
uint16_t netdev_index;
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (sock == -1)
exit(1);
int rtsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (rtsock == -1)
exit(1);
id = netlink_query_family_id(&nlmsg, sock, DEVLINK_FAMILY_NAME, true);
if (id == -1)
goto error;
memset(&genlhdr, 0, sizeof(genlhdr));
genlhdr.cmd = DEVLINK_CMD_PORT_GET;
netlink_init(&nlmsg, id, NLM_F_DUMP, &genlhdr, sizeof(genlhdr));
netlink_attr(&nlmsg, DEVLINK_ATTR_BUS_NAME, bus_name, strlen(bus_name) + 1);
netlink_attr(&nlmsg, DEVLINK_ATTR_DEV_NAME, dev_name, strlen(dev_name) + 1);
err = netlink_send_ext(&nlmsg, sock, id, &total_len, true);
if (err < 0) {
goto error;
}
offset = 0;
netdev_index = 0;
while ((len = netlink_next_msg(&nlmsg, offset, total_len)) != -1) {
struct nlattr* attr = (struct nlattr*)(nlmsg.buf + offset + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr)));
for (; (char*)attr < nlmsg.buf + offset + len; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
if (attr->nla_type == DEVLINK_ATTR_NETDEV_NAME) {
char* port_name;
char netdev_name[IFNAMSIZ];
port_name = (char*)(attr + 1);
snprintf(netdev_name, sizeof(netdev_name), "%s%d", netdev_prefix, netdev_index);
netlink_device_change(&nlmsg2, rtsock, port_name, true, 0, 0, 0, netdev_name);
break;
}
}
offset += len;
netdev_index++;
}
error:
close(rtsock);
close(sock);
}
#define DEV_IPV4 "172.20.20.%d"
#define DEV_IPV6 "fe80::%02x"
#define DEV_MAC 0x00aaaaaaaaaa
static void netdevsim_add(unsigned int addr, unsigned int port_count)
{
write_file("/sys/bus/netdevsim/del_device", "%u", addr);
if (write_file("/sys/bus/netdevsim/new_device", "%u %u", addr, port_count)) {
char buf[32];
snprintf(buf, sizeof(buf), "netdevsim%d", addr);
initialize_devlink_ports("netdevsim", buf, "netdevsim");
}
}
#define WG_GENL_NAME "wireguard"
enum wg_cmd {
WG_CMD_GET_DEVICE,
WG_CMD_SET_DEVICE,
};
enum wgdevice_attribute {
WGDEVICE_A_UNSPEC,
WGDEVICE_A_IFINDEX,
WGDEVICE_A_IFNAME,
WGDEVICE_A_PRIVATE_KEY,
WGDEVICE_A_PUBLIC_KEY,
WGDEVICE_A_FLAGS,
WGDEVICE_A_LISTEN_PORT,
WGDEVICE_A_FWMARK,
WGDEVICE_A_PEERS,
};
enum wgpeer_attribute {
WGPEER_A_UNSPEC,
WGPEER_A_PUBLIC_KEY,
WGPEER_A_PRESHARED_KEY,
WGPEER_A_FLAGS,
WGPEER_A_ENDPOINT,
WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
WGPEER_A_LAST_HANDSHAKE_TIME,
WGPEER_A_RX_BYTES,
WGPEER_A_TX_BYTES,
WGPEER_A_ALLOWEDIPS,
WGPEER_A_PROTOCOL_VERSION,
};
enum wgallowedip_attribute {
WGALLOWEDIP_A_UNSPEC,
WGALLOWEDIP_A_FAMILY,
WGALLOWEDIP_A_IPADDR,
WGALLOWEDIP_A_CIDR_MASK,
};
static void netlink_wireguard_setup(void)
{
const char ifname_a[] = "wg0";
const char ifname_b[] = "wg1";
const char ifname_c[] = "wg2";
const char private_a[] = "\xa0\x5c\xa8\x4f\x6c\x9c\x8e\x38\x53\xe2\xfd\x7a\x70\xae\x0f\xb2\x0f\xa1\x52\x60\x0c\xb0\x08\x45\x17\x4f\x08\x07\x6f\x8d\x78\x43";
const char private_b[] = "\xb0\x80\x73\xe8\xd4\x4e\x91\xe3\xda\x92\x2c\x22\x43\x82\x44\xbb\x88\x5c\x69\xe2\x69\xc8\xe9\xd8\x35\xb1\x14\x29\x3a\x4d\xdc\x6e";
const char private_c[] = "\xa0\xcb\x87\x9a\x47\xf5\xbc\x64\x4c\x0e\x69\x3f\xa6\xd0\x31\xc7\x4a\x15\x53\xb6\xe9\x01\xb9\xff\x2f\x51\x8c\x78\x04\x2f\xb5\x42";
const char public_a[] = "\x97\x5c\x9d\x81\xc9\x83\xc8\x20\x9e\xe7\x81\x25\x4b\x89\x9f\x8e\xd9\x25\xae\x9f\x09\x23\xc2\x3c\x62\xf5\x3c\x57\xcd\xbf\x69\x1c";
const char public_b[] = "\xd1\x73\x28\x99\xf6\x11\xcd\x89\x94\x03\x4d\x7f\x41\x3d\xc9\x57\x63\x0e\x54\x93\xc2\x85\xac\xa4\x00\x65\xcb\x63\x11\xbe\x69\x6b";
const char public_c[] = "\xf4\x4d\xa3\x67\xa8\x8e\xe6\x56\x4f\x02\x02\x11\x45\x67\x27\x08\x2f\x5c\xeb\xee\x8b\x1b\xf5\xeb\x73\x37\x34\x1b\x45\x9b\x39\x22";
const uint16_t listen_a = 20001;
const uint16_t listen_b = 20002;
const uint16_t listen_c = 20003;
const uint16_t af_inet = AF_INET;
const uint16_t af_inet6 = AF_INET6;
const struct sockaddr_in endpoint_b_v4 = {
.sin_family = AF_INET,
.sin_port = htons(listen_b),
.sin_addr = {htonl(INADDR_LOOPBACK)}};
const struct sockaddr_in endpoint_c_v4 = {
.sin_family = AF_INET,
.sin_port = htons(listen_c),
.sin_addr = {htonl(INADDR_LOOPBACK)}};
struct sockaddr_in6 endpoint_a_v6 = {
.sin6_family = AF_INET6,
.sin6_port = htons(listen_a)};
endpoint_a_v6.sin6_addr = in6addr_loopback;
struct sockaddr_in6 endpoint_c_v6 = {
.sin6_family = AF_INET6,
.sin6_port = htons(listen_c)};
endpoint_c_v6.sin6_addr = in6addr_loopback;
const struct in_addr first_half_v4 = {0};
const struct in_addr second_half_v4 = {(uint32_t)htonl(128 << 24)};
const struct in6_addr first_half_v6 = {{{0}}};
const struct in6_addr second_half_v6 = {{{0x80}}};
const uint8_t half_cidr = 1;
const uint16_t persistent_keepalives[] = {1, 3, 7, 9, 14, 19};
struct genlmsghdr genlhdr = {
.cmd = WG_CMD_SET_DEVICE,
.version = 1};
int sock;
int id, err;
sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (sock == -1) {
return;
}
id = netlink_query_family_id(&nlmsg, sock, WG_GENL_NAME, true);
if (id == -1)
goto error;
netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_a, strlen(ifname_a) + 1);
netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_a, 32);
netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_a, 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32);
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, sizeof(endpoint_b_v4));
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[0], 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32);
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v6, sizeof(endpoint_c_v6));
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[1], 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
err = netlink_send(&nlmsg, sock);
if (err < 0) {
}
netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_b, strlen(ifname_b) + 1);
netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_b, 32);
netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_b, 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32);
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, sizeof(endpoint_a_v6));
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[2], 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32);
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v4, sizeof(endpoint_c_v4));
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[3], 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
err = netlink_send(&nlmsg, sock);
if (err < 0) {
}
netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_c, strlen(ifname_c) + 1);
netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_c, 32);
netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_c, 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32);
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, sizeof(endpoint_a_v6));
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[4], 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32);
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, sizeof(endpoint_b_v4));
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[5], 2);
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_nest(&nlmsg, NLA_F_NESTED | 0);
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
netlink_done(&nlmsg);
err = netlink_send(&nlmsg, sock);
if (err < 0) {
}
error:
close(sock);
}
static void initialize_netdevices(void)
{
char netdevsim[16];
sprintf(netdevsim, "netdevsim%d", (int)procid);
struct {
const char* type;
const char* dev;
} devtypes[] = {
{"ip6gretap", "ip6gretap0"},
{"bridge", "bridge0"},
{"vcan", "vcan0"},
{"bond", "bond0"},
{"team", "team0"},
{"dummy", "dummy0"},
{"nlmon", "nlmon0"},
{"caif", "caif0"},
{"batadv", "batadv0"},
{"vxcan", "vxcan1"},
{"veth", 0},
{"wireguard", "wg0"},
{"wireguard", "wg1"},
{"wireguard", "wg2"},
};
const char* devmasters[] = {"bridge", "bond", "team", "batadv"};
struct {
const char* name;
int macsize;
bool noipv6;
} devices[] = {
{"lo", ETH_ALEN},
{"sit0", 0},
{"bridge0", ETH_ALEN},
{"vcan0", 0, true},
{"tunl0", 0},
{"gre0", 0},
{"gretap0", ETH_ALEN},
{"ip_vti0", 0},
{"ip6_vti0", 0},
{"ip6tnl0", 0},
{"ip6gre0", 0},
{"ip6gretap0", ETH_ALEN},
{"erspan0", ETH_ALEN},
{"bond0", ETH_ALEN},
{"veth0", ETH_ALEN},
{"veth1", ETH_ALEN},
{"team0", ETH_ALEN},
{"veth0_to_bridge", ETH_ALEN},
{"veth1_to_bridge", ETH_ALEN},
{"veth0_to_bond", ETH_ALEN},
{"veth1_to_bond", ETH_ALEN},
{"veth0_to_team", ETH_ALEN},
{"veth1_to_team", ETH_ALEN},
{"veth0_to_hsr", ETH_ALEN},
{"veth1_to_hsr", ETH_ALEN},
{"hsr0", 0},
{"dummy0", ETH_ALEN},
{"nlmon0", 0},
{"vxcan0", 0, true},
{"vxcan1", 0, true},
{"caif0", ETH_ALEN},
{"batadv0", ETH_ALEN},
{netdevsim, ETH_ALEN},
{"xfrm0", ETH_ALEN},
{"veth0_virt_wifi", ETH_ALEN},
{"veth1_virt_wifi", ETH_ALEN},
{"virt_wifi0", ETH_ALEN},
{"veth0_vlan", ETH_ALEN},
{"veth1_vlan", ETH_ALEN},
{"vlan0", ETH_ALEN},
{"vlan1", ETH_ALEN},
{"macvlan0", ETH_ALEN},
{"macvlan1", ETH_ALEN},
{"ipvlan0", ETH_ALEN},
{"ipvlan1", ETH_ALEN},
{"veth0_macvtap", ETH_ALEN},
{"veth1_macvtap", ETH_ALEN},
{"macvtap0", ETH_ALEN},
{"macsec0", ETH_ALEN},
{"veth0_to_batadv", ETH_ALEN},
{"veth1_to_batadv", ETH_ALEN},
{"batadv_slave_0", ETH_ALEN},
{"batadv_slave_1", ETH_ALEN},
{"geneve0", ETH_ALEN},
{"geneve1", ETH_ALEN},
{"wg0", 0},
{"wg1", 0},
{"wg2", 0},
};
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sock == -1)
exit(1);
unsigned i;
for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++)
netlink_add_device(&nlmsg, sock, devtypes[i].type, devtypes[i].dev);
for (i = 0; i < sizeof(devmasters) / (sizeof(devmasters[0])); i++) {
char master[32], slave0[32], veth0[32], slave1[32], veth1[32];
sprintf(slave0, "%s_slave_0", devmasters[i]);
sprintf(veth0, "veth0_to_%s", devmasters[i]);
netlink_add_veth(&nlmsg, sock, slave0, veth0);
sprintf(slave1, "%s_slave_1", devmasters[i]);
sprintf(veth1, "veth1_to_%s", devmasters[i]);
netlink_add_veth(&nlmsg, sock, slave1, veth1);
sprintf(master, "%s0", devmasters[i]);
netlink_device_change(&nlmsg, sock, slave0, false, master, 0, 0, NULL);
netlink_device_change(&nlmsg, sock, slave1, false, master, 0, 0, NULL);
}
netlink_add_xfrm(&nlmsg, sock, "xfrm0");
netlink_device_change(&nlmsg, sock, "bridge_slave_0", true, 0, 0, 0, NULL);
netlink_device_change(&nlmsg, sock, "bridge_slave_1", true, 0, 0, 0, NULL);
netlink_add_veth(&nlmsg, sock, "hsr_slave_0", "veth0_to_hsr");
netlink_add_veth(&nlmsg, sock, "hsr_slave_1", "veth1_to_hsr");
netlink_add_hsr(&nlmsg, sock, "hsr0", "hsr_slave_0", "hsr_slave_1");
netlink_device_change(&nlmsg, sock, "hsr_slave_0", true, 0, 0, 0, NULL);
netlink_device_change(&nlmsg, sock, "hsr_slave_1", true, 0, 0, 0, NULL);
netlink_add_veth(&nlmsg, sock, "veth0_virt_wifi", "veth1_virt_wifi");
netlink_add_linked(&nlmsg, sock, "virt_wifi", "virt_wifi0", "veth1_virt_wifi");
netlink_add_veth(&nlmsg, sock, "veth0_vlan", "veth1_vlan");
netlink_add_vlan(&nlmsg, sock, "vlan0", "veth0_vlan", 0, htons(ETH_P_8021Q));
netlink_add_vlan(&nlmsg, sock, "vlan1", "veth0_vlan", 1, htons(ETH_P_8021AD));
netlink_add_macvlan(&nlmsg, sock, "macvlan0", "veth1_vlan");
netlink_add_macvlan(&nlmsg, sock, "macvlan1", "veth1_vlan");
netlink_add_ipvlan(&nlmsg, sock, "ipvlan0", "veth0_vlan", IPVLAN_MODE_L2, 0);
netlink_add_ipvlan(&nlmsg, sock, "ipvlan1", "veth0_vlan", IPVLAN_MODE_L3S, IPVLAN_F_VEPA);
netlink_add_veth(&nlmsg, sock, "veth0_macvtap", "veth1_macvtap");
netlink_add_linked(&nlmsg, sock, "macvtap", "macvtap0", "veth0_macvtap");
netlink_add_linked(&nlmsg, sock, "macsec", "macsec0", "veth1_macvtap");
char addr[32];
sprintf(addr, DEV_IPV4, 14 + 10);
struct in_addr geneve_addr4;
if (inet_pton(AF_INET, addr, &geneve_addr4) <= 0)
exit(1);
struct in6_addr geneve_addr6;
if (inet_pton(AF_INET6, "fc00::01", &geneve_addr6) <= 0)
exit(1);
netlink_add_geneve(&nlmsg, sock, "geneve0", 0, &geneve_addr4, 0);
netlink_add_geneve(&nlmsg, sock, "geneve1", 1, 0, &geneve_addr6);
netdevsim_add((int)procid, 4);
netlink_wireguard_setup();
for (i = 0; i < sizeof(devices) / (sizeof(devices[0])); i++) {
char addr[32];
sprintf(addr, DEV_IPV4, i + 10);
netlink_add_addr4(&nlmsg, sock, devices[i].name, addr);
if (!devices[i].noipv6) {
sprintf(addr, DEV_IPV6, i + 10);
netlink_add_addr6(&nlmsg, sock, devices[i].name, addr);
}
uint64_t macaddr = DEV_MAC + ((i + 10ull) << 40);
netlink_device_change(&nlmsg, sock, devices[i].name, true, 0, &macaddr, devices[i].macsize, NULL);
}
close(sock);
}
static void initialize_netdevices_init(void)
{
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sock == -1)
exit(1);
struct {
const char* type;
int macsize;
bool noipv6;
bool noup;
} devtypes[] = {
{"nr", 7, true},
{"rose", 5, true, true},
};
unsigned i;
for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++) {
char dev[32], addr[32];
sprintf(dev, "%s%d", devtypes[i].type, (int)procid);
sprintf(addr, "172.30.%d.%d", i, (int)procid + 1);
netlink_add_addr4(&nlmsg, sock, dev, addr);
if (!devtypes[i].noipv6) {
sprintf(addr, "fe88::%02x:%02x", i, (int)procid + 1);
netlink_add_addr6(&nlmsg, sock, dev, addr);
}
int macsize = devtypes[i].macsize;
uint64_t macaddr = 0xbbbbbb + ((unsigned long long)i << (8 * (macsize - 2))) +
(procid << (8 * (macsize - 1)));
netlink_device_change(&nlmsg, sock, dev, !devtypes[i].noup, 0, &macaddr, macsize, NULL);
}
close(sock);
}
#define MAX_FDS 30
static long syz_genetlink_get_family_id(volatile long name, volatile long sock_arg)
{
int fd = sock_arg;
if (fd < 0) {
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
if (fd == -1) {
return -1;
}
}
struct nlmsg nlmsg_tmp;
int ret = netlink_query_family_id(&nlmsg_tmp, fd, (char*)name, false);
if ((int)sock_arg < 0)
close(fd);
if (ret < 0) {
return -1;
}
return ret;
}
static void setup_gadgetfs();
static void setup_binderfs();
static void setup_fusectl();
static void sandbox_common_mount_tmpfs(void)
{
write_file("/proc/sys/fs/mount-max", "100000");
if (mkdir("./syz-tmp", 0777))
exit(1);
if (mount("", "./syz-tmp", "tmpfs", 0, NULL))
exit(1);
if (mkdir("./syz-tmp/newroot", 0777))
exit(1);
if (mkdir("./syz-tmp/newroot/dev", 0700))
exit(1);
unsigned bind_mount_flags = MS_BIND | MS_REC | MS_PRIVATE;
if (mount("/dev", "./syz-tmp/newroot/dev", NULL, bind_mount_flags, NULL))
exit(1);
if (mkdir("./syz-tmp/newroot/proc", 0700))
exit(1);
if (mount("syz-proc", "./syz-tmp/newroot/proc", "proc", 0, NULL))
exit(1);
if (mkdir("./syz-tmp/newroot/selinux", 0700))
exit(1);
const char* selinux_path = "./syz-tmp/newroot/selinux";
if (mount("/selinux", selinux_path, NULL, bind_mount_flags, NULL)) {
if (errno != ENOENT)
exit(1);
if (mount("/sys/fs/selinux", selinux_path, NULL, bind_mount_flags, NULL) && errno != ENOENT)
exit(1);
}
if (mkdir("./syz-tmp/newroot/sys", 0700))
exit(1);
if (mount("/sys", "./syz-tmp/newroot/sys", 0, bind_mount_flags, NULL))
exit(1);
if (mount("/sys/kernel/debug", "./syz-tmp/newroot/sys/kernel/debug", NULL, bind_mount_flags, NULL) && errno != ENOENT)
exit(1);
if (mount("/sys/fs/smackfs", "./syz-tmp/newroot/sys/fs/smackfs", NULL, bind_mount_flags, NULL) && errno != ENOENT)
exit(1);
if (mount("/proc/sys/fs/binfmt_misc", "./syz-tmp/newroot/proc/sys/fs/binfmt_misc", NULL, bind_mount_flags, NULL) && errno != ENOENT)
exit(1);
if (mkdir("./syz-tmp/newroot/syz-inputs", 0700))
exit(1);
if (mount("/syz-inputs", "./syz-tmp/newroot/syz-inputs", NULL, bind_mount_flags | MS_RDONLY, NULL) && errno != ENOENT)
exit(1);
if (mkdir("./syz-tmp/pivot", 0777))
exit(1);
if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) {
if (chdir("./syz-tmp"))
exit(1);
} else {
if (chdir("/"))
exit(1);
if (umount2("./pivot", MNT_DETACH))
exit(1);
}
if (chroot("./newroot"))
exit(1);
if (chdir("/"))
exit(1);
setup_gadgetfs();
setup_binderfs();
setup_fusectl();
}
static void setup_gadgetfs()
{
if (mkdir("/dev/gadgetfs", 0777)) {
}
if (mount("gadgetfs", "/dev/gadgetfs", "gadgetfs", 0, NULL)) {
}
}
static void setup_fusectl()
{
if (mount(0, "/sys/fs/fuse/connections", "fusectl", 0, 0)) {
}
}
static void setup_binderfs()
{
if (mkdir("/dev/binderfs", 0777)) {
}
if (mount("binder", "/dev/binderfs", "binder", 0, NULL)) {
}
if (symlink("/dev/binderfs", "./binderfs")) {
}
}
static void loop();
static void sandbox_common()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
if (getppid() == 1)
exit(1);
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = (200 << 20);
setrlimit(RLIMIT_AS, &rlim);
rlim.rlim_cur = rlim.rlim_max = 32 << 20;
setrlimit(RLIMIT_MEMLOCK, &rlim);
rlim.rlim_cur = rlim.rlim_max = 136 << 20;
setrlimit(RLIMIT_FSIZE, &rlim);
rlim.rlim_cur = rlim.rlim_max = 1 << 20;
setrlimit(RLIMIT_STACK, &rlim);
rlim.rlim_cur = rlim.rlim_max = 128 << 20;
setrlimit(RLIMIT_CORE, &rlim);
rlim.rlim_cur = rlim.rlim_max = 256;
setrlimit(RLIMIT_NOFILE, &rlim);
if (unshare(CLONE_NEWNS)) {
}
if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
}
if (unshare(CLONE_NEWIPC)) {
}
if (unshare(0x02000000)) {
}
if (unshare(CLONE_NEWUTS)) {
}
if (unshare(CLONE_SYSVSEM)) {
}
typedef struct {
const char* name;
const char* value;
} sysctl_t;
static const sysctl_t sysctls[] = {
{"/proc/sys/kernel/shmmax", "16777216"},
{"/proc/sys/kernel/shmall", "536870912"},
{"/proc/sys/kernel/shmmni", "1024"},
{"/proc/sys/kernel/msgmax", "8192"},
{"/proc/sys/kernel/msgmni", "1024"},
{"/proc/sys/kernel/msgmnb", "1024"},
{"/proc/sys/kernel/sem", "1024 1048576 500 1024"},
};
unsigned i;
for (i = 0; i < sizeof(sysctls) / sizeof(sysctls[0]); i++)
write_file(sysctls[i].name, sysctls[i].value);
}
static int wait_for_loop(int pid)
{
if (pid < 0)
exit(1);
int status = 0;
while (waitpid(-1, &status, __WALL) != pid) {
}
return WEXITSTATUS(status);
}
static void drop_caps(void)
{
struct __user_cap_header_struct cap_hdr = {};
struct __user_cap_data_struct cap_data[2] = {};
cap_hdr.version = _LINUX_CAPABILITY_VERSION_3;
cap_hdr.pid = getpid();
if (syscall(SYS_capget, &cap_hdr, &cap_data))
exit(1);
const int drop = (1 << CAP_SYS_PTRACE) | (1 << CAP_SYS_NICE);
cap_data[0].effective &= ~drop;
cap_data[0].permitted &= ~drop;
cap_data[0].inheritable &= ~drop;
if (syscall(SYS_capset, &cap_hdr, &cap_data))
exit(1);
}
static int do_sandbox_none(void)
{
if (unshare(CLONE_NEWPID)) {
}
int pid = fork();
if (pid != 0)
return wait_for_loop(pid);
sandbox_common();
drop_caps();
initialize_netdevices_init();
if (unshare(CLONE_NEWNET)) {
}
write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535");
initialize_netdevices();
sandbox_common_mount_tmpfs();
loop();
exit(1);
}
static void kill_and_wait(int pid, int* status)
{
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
for (int i = 0; i < 100; i++) {
if (waitpid(-1, status, WNOHANG | __WALL) == pid)
return;
usleep(1000);
}
DIR* dir = opendir("/sys/fs/fuse/connections");
if (dir) {
for (;;) {
struct dirent* ent = readdir(dir);
if (!ent)
break;
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
char abort[300];
snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", ent->d_name);
int fd = open(abort, O_WRONLY);
if (fd == -1) {
continue;
}
if (write(fd, abort, 1) < 0) {
}
close(fd);
}
closedir(dir);
} else {
}
while (waitpid(-1, status, __WALL) != pid) {
}
}
static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
write_file("/proc/self/oom_score_adj", "1000");
}
static void close_fds()
{
for (int fd = 3; fd < MAX_FDS; fd++)
close(fd);
}
#define USLEEP_FORKED_CHILD (3 * 50 *1000)
static long handle_clone_ret(long ret)
{
if (ret != 0) {
return ret;
}
usleep(USLEEP_FORKED_CHILD);
syscall(__NR_exit, 0);
while (1) {
}
}
static long syz_clone(volatile long flags, volatile long stack, volatile long stack_len,
volatile long ptid, volatile long ctid, volatile long tls)
{
long sp = (stack + stack_len) & ~15;
long ret = (long)syscall(__NR_clone, flags & ~CLONE_VM, sp, ptid, ctid, tls);
return handle_clone_ret(ret);
}
struct thread_t {
int created, call;
event_t ready, done;
};
static struct thread_t threads[16];
static void execute_call(int call);
static int running;
static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}
static void execute_one(void)
{
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
}
int i, call, thread;
for (call = 0; call < 9; call++) {
for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0])); thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
event_timedwait(&th->done, 50);
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
close_fds();
}
static void execute_one(void);
#define WAIT_FLAGS __WALL
static void loop(void)
{
int iter = 0;
for (;; iter++) {
int pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
setup_test();
execute_one();
exit(0);
}
int status = 0;
uint64_t start = current_time_ms();
for (;;) {
sleep_ms(10);
if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
break;
if (current_time_ms() - start < 5000)
continue;
kill_and_wait(pid, &status);
break;
}
}
}
uint64_t r[5] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff};
void execute_call(int call)
{
intptr_t res = 0;
switch (call) {
case 0:
// socket$nl_generic arguments: [
// domain: const = 0x10 (8 bytes)
// type: const = 0x3 (8 bytes)
// proto: const = 0x10 (4 bytes)
// ]
// returns sock_nl_generic
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/3ul, /*proto=*/0x10);
if (res != -1)
r[0] = res;
break;
case 1:
// syz_genetlink_get_family_id$devlink arguments: [
// name: ptr[in, buffer] {
// buffer: {64 65 76 6c 69 6e 6b 00} (length 0x8)
// }
// fd: sock_nl_generic (resource)
// ]
// returns genl_devlink_family_id
memcpy((void*)0x200000000080, "devlink\000", 8);
res = -1;
res = syz_genetlink_get_family_id(/*name=*/0x200000000080, /*fd=*/-1);
if (res != -1)
r[1] = res;
break;
case 2:
// gettid arguments: [
// ]
// returns pid
res = syscall(__NR_gettid);
if (res != -1)
r[2] = res;
break;
case 3:
// sendmsg$DEVLINK_CMD_RELOAD arguments: [
// fd: sock_nl_generic (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_t[genl_devlink_family_id, genlmsghdr_t[DEVLINK_CMD_RELOAD], devlink_reload_policy]]] {
// msghdr_netlink[netlink_msg_t[genl_devlink_family_id, genlmsghdr_t[DEVLINK_CMD_RELOAD], devlink_reload_policy]] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_t[genl_devlink_family_id, genlmsghdr_t[DEVLINK_CMD_RELOAD], devlink_reload_policy]]] {
// iovec[in, netlink_msg_t[genl_devlink_family_id, genlmsghdr_t[DEVLINK_CMD_RELOAD], devlink_reload_policy]] {
// addr: ptr[in, netlink_msg_t[genl_devlink_family_id, genlmsghdr_t[DEVLINK_CMD_RELOAD], devlink_reload_policy]] {
// netlink_msg_t[genl_devlink_family_id, genlmsghdr_t[DEVLINK_CMD_RELOAD], devlink_reload_policy] {
// len: len = 0x3c (4 bytes)
// type: genl_devlink_family_id (resource)
// flags: netlink_msg_flags = 0x536ae464467e3e0b (2 bytes)
// seq: int32 = 0x0 (4 bytes)
// pid: int32 = 0x0 (4 bytes)
// payload: genlmsghdr_t[DEVLINK_CMD_RELOAD] {
// cmd: const = 0x25 (1 bytes)
// version: const = 0x0 (1 bytes)
// reserved: const = 0x0 (2 bytes)
// }
// attrs: array[devlink_reload_policy] {
// devlink_reload_policy {
// handle: union devlink_handle {
// nsim: devlink_nl_policy$nsim {
// DEVLINK_ATTR_BUS_NAME: nlattr_t[const[DEVLINK_ATTR_BUS_NAME, int16], string["netdevsim"]] {
// nla_len: offsetof = 0xe (2 bytes)
// nla_type: const = 0x1 (2 bytes)
// payload: buffer: {6e 65 74 64 65 76 73 69 6d 00} (length 0xa)
// size: buffer: {} (length 0x0)
// pad = 0x0 (2 bytes)
// }
// DEVLINK_ATTR_DEV_NAME: nlattr_t[const[DEVLINK_ATTR_DEV_NAME, int16], devlink_devname] {
// nla_len: offsetof = 0xf (2 bytes)
// nla_type: const = 0x2 (2 bytes)
// payload: devlink_devname {
// prefix: buffer: {6e 65 74 64 65 76 73 69 6d} (length 0x9)
// id: proc = 0x0 (1 bytes)
// z: const = 0x0 (1 bytes)
// }
// size: buffer: {} (length 0x0)
// pad = 0x0 (1 bytes)
// }
// }
// }
// arg: union devlink_nl_policy$reload {
// DEVLINK_ATTR_NETNS_PID: nlattr_t[const[DEVLINK_ATTR_NETNS_PID, int16], pid] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x8b (2 bytes)
// payload: pid (resource)
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// }
// len: len = 0x3c (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x0 (8 bytes)
// ]
*(uint64_t*)0x200000000800 = 0;
*(uint32_t*)0x200000000808 = 0;
*(uint64_t*)0x200000000810 = 0x200000000380;
*(uint64_t*)0x200000000380 = 0x200000000000;
*(uint32_t*)0x200000000000 = 0x3c;
*(uint16_t*)0x200000000004 = r[1];
*(uint16_t*)0x200000000006 = 0x3e0b;
*(uint32_t*)0x200000000008 = 0;
*(uint32_t*)0x20000000000c = 0;
*(uint8_t*)0x200000000010 = 0x25;
*(uint8_t*)0x200000000011 = 0;
*(uint16_t*)0x200000000012 = 0;
*(uint16_t*)0x200000000014 = 0xe;
*(uint16_t*)0x200000000016 = 1;
memcpy((void*)0x200000000018, "netdevsim\000", 10);
*(uint16_t*)0x200000000024 = 0xf;
*(uint16_t*)0x200000000026 = 2;
memcpy((void*)0x200000000028, "netdevsim", 9);
*(uint8_t*)0x200000000031 = 0x30;
*(uint8_t*)0x200000000032 = 0;
*(uint16_t*)0x200000000034 = 8;
*(uint16_t*)0x200000000036 = 0x8b;
*(uint32_t*)0x200000000038 = r[2];
*(uint64_t*)0x200000000388 = 0x3c;
*(uint64_t*)0x200000000818 = 1;
*(uint64_t*)0x200000000820 = 0;
*(uint64_t*)0x200000000828 = 0;
*(uint32_t*)0x200000000830 = 0;
syscall(__NR_sendmsg, /*fd=*/r[0], /*msg=*/0x200000000800ul, /*f=*/0ul);
break;
case 4:
// syz_clone arguments: [
// flags: clone_flags = 0x40b04000 (8 bytes)
// stack: nil
// stack_len: bytesize = 0x0 (8 bytes)
// parentid: nil
// childtid: nil
// tls: nil
// ]
// returns pid
syz_clone(/*flags=CLONE_NEWNET|CLONE_UNTRACED|CLONE_CHILD_CLEARTID|CLONE_PARENT_SETTID|CLONE_VFORK*/0x40b04000, /*stack=*/0, /*stack_len=*/0, /*parentid=*/0, /*childtid=*/0, /*tls=*/0);
break;
case 5:
// socket$netlink arguments: [
// domain: const = 0x10 (8 bytes)
// type: const = 0x3 (8 bytes)
// proto: netlink_proto = 0x0 (4 bytes)
// ]
// returns sock_netlink
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/3ul, /*proto=*/0);
if (res != -1)
r[3] = res;
break;
case 6:
// sendmsg$nl_route arguments: [
// fd: sock_nl_route (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_route]] {
// msghdr_netlink[netlink_msg_route] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_route]] {
// iovec[in, netlink_msg_route] {
// addr: ptr[in, netlink_msg_route] {
// union netlink_msg_route {
// newlink: netlink_msg_t[const[RTM_NEWLINK, int16], ifinfomsg[AF_UNSPEC], ifla_policy] {
// len: len = 0x28 (4 bytes)
// type: const = 0x10 (2 bytes)
// flags: netlink_msg_flags = 0x1 (2 bytes)
// seq: int32 = 0x0 (4 bytes)
// pid: int32 = 0x0 (4 bytes)
// payload: ifinfomsg[AF_UNSPEC] {
// ifi_family: const = 0x0 (1 bytes)
// __ifi_pad: const = 0x0 (1 bytes)
// ifi_type: const = 0x0 (2 bytes)
// ifi_index: ifindex (resource)
// ifi_flags: net_device_flags = 0xf0ffff (4 bytes)
// ifi_change: net_device_flags = 0x0 (4 bytes)
// }
// attrs: array[ifla_policy] {
// union ifla_policy {
// IFLA_GROUP: nlattr_t[const[IFLA_GROUP, int16], int32] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x1b (2 bytes)
// payload: int32 = 0x0 (4 bytes)
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// }
// len: len = 0x28 (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x0 (8 bytes)
// ]
*(uint64_t*)0x2000000000c0 = 0;
*(uint32_t*)0x2000000000c8 = 0;
*(uint64_t*)0x2000000000d0 = 0x2000000013c0;
*(uint64_t*)0x2000000013c0 = 0x200000000040;
*(uint32_t*)0x200000000040 = 0x28;
*(uint16_t*)0x200000000044 = 0x10;
*(uint16_t*)0x200000000046 = 1;
*(uint32_t*)0x200000000048 = 0;
*(uint32_t*)0x20000000004c = 0;
*(uint8_t*)0x200000000050 = 0;
*(uint8_t*)0x200000000051 = 0;
*(uint16_t*)0x200000000052 = 0;
*(uint32_t*)0x200000000054 = 0;
*(uint32_t*)0x200000000058 = 0xf0ffff;
*(uint32_t*)0x20000000005c = 0;
*(uint16_t*)0x200000000060 = 8;
*(uint16_t*)0x200000000062 = 0x1b;
*(uint32_t*)0x200000000064 = 0;
*(uint64_t*)0x2000000013c8 = 0x28;
*(uint64_t*)0x2000000000d8 = 1;
*(uint64_t*)0x2000000000e0 = 0;
*(uint64_t*)0x2000000000e8 = 0;
*(uint32_t*)0x2000000000f0 = 0;
syscall(__NR_sendmsg, /*fd=*/r[3], /*msg=*/0x2000000000c0ul, /*f=*/0ul);
break;
case 7:
// socket$nl_route arguments: [
// domain: const = 0x10 (8 bytes)
// type: const = 0x3 (8 bytes)
// proto: const = 0x0 (4 bytes)
// ]
// returns sock_nl_route
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/3ul, /*proto=*/0);
if (res != -1)
r[4] = res;
break;
case 8:
// sendmsg$nl_route_sched arguments: [
// fd: sock_nl_route (resource)
// msg: ptr[in, msghdr_netlink[netlink_msg_route_sched]] {
// msghdr_netlink[netlink_msg_route_sched] {
// addr: nil
// addrlen: len = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// vec: ptr[in, iovec[in, netlink_msg_route_sched]] {
// iovec[in, netlink_msg_route_sched] {
// addr: ptr[in, netlink_msg_route_sched] {
// union netlink_msg_route_sched {
// newqdisc: netlink_msg_t[const[RTM_NEWQDISC, int16], tcmsg[AF_UNSPEC], rtm_tca_policy] {
// len: len = 0x54 (4 bytes)
// type: const = 0x10 (2 bytes)
// flags: netlink_msg_flags = 0x1 (2 bytes)
// seq: int32 = 0x0 (4 bytes)
// pid: int32 = 0x0 (4 bytes)
// payload: tcmsg[AF_UNSPEC] {
// family: const = 0x6 (1 bytes)
// tcm__pad1: const = 0x0 (1 bytes)
// tcm__pad2: const = 0x8100 (2 bytes)
// ifindex: ifindex (resource)
// tcm_handle: tcm_handle {
// minor: tcm_handle_offsets = 0x0 (2 bytes)
// major: tcm_handle_offsets = 0x0 (2 bytes)
// }
// tcm_parent: tcm_handle {
// minor: tcm_handle_offsets = 0xfff1 (2 bytes)
// major: tcm_handle_offsets = 0x0 (2 bytes)
// }
// tcm_info: tcm_handle {
// minor: tcm_handle_offsets = 0xe (2 bytes)
// major: tcm_handle_offsets = 0x10 (2 bytes)
// }
// }
// attrs: array[rtm_tca_policy] {
// union rtm_tca_policy {
// TCA_EGRESS_BLOCK: nlattr_t[const[TCA_EGRESS_BLOCK, int16], int32] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0xe (2 bytes)
// payload: int32 = 0x7 (4 bytes)
// size: buffer: {} (length 0x0)
// }
// }
// union rtm_tca_policy {
// TCA_STAB: nlattr_tt[const[TCA_STAB, int16:14], 0, 1, array[stab_policy]] {
// nla_len: offsetof = 0x28 (2 bytes)
// nla_type: const = 0x8 (1 bytes)
// NLA_F_NET_BYTEORDER: const = 0x0 (0 bytes)
// NLA_F_NESTED: const = 0x1 (1 bytes)
// payload: array[stab_policy] {
// stab_policy {
// TCA_STAB_BASE: nlattr_t[const[TCA_STAB_BASE, int16], tc_sizespec] {
// nla_len: offsetof = 0x1c (2 bytes)
// nla_type: const = 0x11 (2 bytes)
// payload: tc_sizespec {
// cell_log: int8 = 0x0 (1 bytes)
// size_log: int8 = 0x0 (1 bytes)
// cell_align: int16 = 0x0 (2 bytes)
// overhead: int32 = 0x0 (4 bytes)
// linklayer: linklayer = 0x0 (4 bytes)
// mpu: int32 = 0x5e06209c (4 bytes)
// mtu: int32 = 0x0 (4 bytes)
// tsize: len = 0x2 (4 bytes)
// }
// size: buffer: {} (length 0x0)
// }
// TCA_STAB_DATA: nlattr_t[const[TCA_STAB_DATA, int16], array[int16]] {
// nla_len: offsetof = 0x8 (2 bytes)
// nla_type: const = 0x1b (2 bytes)
// payload: array[int16] {
// int16 = 0x0 (2 bytes)
// int16 = 0x0 (2 bytes)
// }
// size: buffer: {} (length 0x0)
// }
// }
// }
// size: buffer: {} (length 0x0)
// }
// }
// }
// }
// }
// }
// len: len = 0x54 (8 bytes)
// }
// }
// vlen: const = 0x1 (8 bytes)
// ctrl: const = 0x0 (8 bytes)
// ctrllen: const = 0x0 (8 bytes)
// f: send_flags = 0x0 (4 bytes)
// pad = 0x0 (4 bytes)
// }
// }
// f: send_flags = 0x0 (8 bytes)
// ]
*(uint64_t*)0x200000000180 = 0;
*(uint32_t*)0x200000000188 = 0;
*(uint64_t*)0x200000000190 = 0x200000000280;
*(uint64_t*)0x200000000280 = 0x2000000001c0;
*(uint32_t*)0x2000000001c0 = 0x54;
*(uint16_t*)0x2000000001c4 = 0x10;
*(uint16_t*)0x2000000001c6 = 1;
*(uint32_t*)0x2000000001c8 = 0;
*(uint32_t*)0x2000000001cc = 0;
*(uint8_t*)0x2000000001d0 = 6;
*(uint8_t*)0x2000000001d1 = 0;
*(uint16_t*)0x2000000001d2 = 0x8100;
*(uint32_t*)0x2000000001d4 = 0;
*(uint16_t*)0x2000000001d8 = 0;
*(uint16_t*)0x2000000001da = 0;
*(uint16_t*)0x2000000001dc = 0xfff1;
*(uint16_t*)0x2000000001de = 0;
*(uint16_t*)0x2000000001e0 = 0xe;
*(uint16_t*)0x2000000001e2 = 0x10;
*(uint16_t*)0x2000000001e4 = 8;
*(uint16_t*)0x2000000001e6 = 0xe;
*(uint32_t*)0x2000000001e8 = 7;
*(uint16_t*)0x2000000001ec = 0x28;
STORE_BY_BITMASK(uint16_t, , 0x2000000001ee, 8, 0, 14);
STORE_BY_BITMASK(uint16_t, , 0x2000000001ef, 0, 6, 1);
STORE_BY_BITMASK(uint16_t, , 0x2000000001ef, 1, 7, 1);
*(uint16_t*)0x2000000001f0 = 0x1c;
*(uint16_t*)0x2000000001f2 = 0x11;
*(uint8_t*)0x2000000001f4 = 0;
*(uint8_t*)0x2000000001f5 = 0;
*(uint16_t*)0x2000000001f6 = 0;
*(uint32_t*)0x2000000001f8 = 0;
*(uint32_t*)0x2000000001fc = 0;
*(uint32_t*)0x200000000200 = 0x5e06209c;
*(uint32_t*)0x200000000204 = 0;
*(uint32_t*)0x200000000208 = 2;
*(uint16_t*)0x20000000020c = 8;
*(uint16_t*)0x20000000020e = 0x1b;
*(uint16_t*)0x200000000210 = 0;
*(uint16_t*)0x200000000212 = 0;
*(uint64_t*)0x200000000288 = 0x54;
*(uint64_t*)0x200000000198 = 1;
*(uint64_t*)0x2000000001a0 = 0;
*(uint64_t*)0x2000000001a8 = 0;
*(uint32_t*)0x2000000001b0 = 0;
syscall(__NR_sendmsg, /*fd=*/r[4], /*msg=*/0x200000000180ul, /*f=*/0ul);
break;
}
}
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
do_sandbox_none();
return 0;
}
^ permalink raw reply
* Re: [PATCH v3 01/23] xen: arm: move declaration of map_device_irqs_to_domain() to common header
From: Oleksii Kurochko @ 2026-06-24 9:00 UTC (permalink / raw)
To: Orzel, Michal, xen-devel
Cc: Romain Caritey, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
In-Reply-To: <b91ad9b2-b91d-4649-872e-0ba24692f19d@amd.com>
On 6/24/26 9:02 AM, Orzel, Michal wrote:
>
>
> On 17-Jun-26 13:17, Oleksii Kurochko wrote:
>> As map_device_irqs_to_domain() is used unconditionally by common part of
>> dom0less code it is moved to common header.
> `it` here reads as if you were moving the function, not the prototype. Also, use
> imperative mood i.e. `... code, move the prototype to a common header`.
I will apply your suggestion.
>
>>
>> fdt-domain-build.h is chosen as map_device_irqs_to_domain() could be
>> also called indirectly in Arm's DOM0-related code.
> By `indirectly` do you mean `handle_device`? It can also be used in the same way
> by DT overlay feature.
Yes, I meant `handle_device`. I will update the commit message then to:
"... Arm's DOM0-related code and DT overlay feature"
>
>>
>> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
>> ---
>> Changes in v3:
>> - Add tag arm and move this patch earlier before RISC-V-related patches.
>> ---
>> Changes in v2:
>> - New patch.
>> ---
>> xen/arch/arm/include/asm/setup.h | 3 ---
>> xen/include/xen/fdt-domain-build.h | 13 +++++++++++++
>> 2 files changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
>> index 0d29b46ea52b..0adfa4993a8f 100644
>> --- a/xen/arch/arm/include/asm/setup.h
>> +++ b/xen/arch/arm/include/asm/setup.h
>> @@ -53,9 +53,6 @@ void init_traps(void);
>> int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt,
>> struct rangeset *iomem_ranges, struct rangeset *irq_ranges);
>>
>> -int map_device_irqs_to_domain(struct domain *d, struct dt_device_node *dev,
>> - bool need_mapping, struct rangeset *irq_ranges);
>> -
>> int map_irq_to_domain(struct domain *d, unsigned int irq,
>> bool need_mapping, const char *devname);
>>
>> diff --git a/xen/include/xen/fdt-domain-build.h b/xen/include/xen/fdt-domain-build.h
>> index 671486c1c837..8612e98dfda5 100644
>> --- a/xen/include/xen/fdt-domain-build.h
>> +++ b/xen/include/xen/fdt-domain-build.h
> I don't see fdt-domain-build.h being included in Arm's device.c, where the
> definition (that needs to see the prototype) resides.
Agree, it should be added to Arm's device.c. I'll do that in the next
version.
>
>> @@ -12,6 +12,7 @@
>>
>> struct domain;
>> struct page_info;
>> +struct rangeset;
>> struct membanks;
>>
>> typedef bool (*alloc_domheap_mem_cb)(struct domain *d, struct page_info *pg,
>> @@ -79,6 +80,18 @@ static inline void set_domain_type(struct domain *d, const struct kernel_info *k
>> #endif
>> }
>>
>> +/*
>> + * Retrieves the interrupts configuration from a device tree node and maps
>> + * those interrupts to the target domain.
>> + *
>> + * Returns:
>> + * < 0 error
>> + * 0 success
>> + */
> By adding the description to a prototype, there's no need for it to also exist
> at the definition.
I will drop it than.
>> +int map_device_irqs_to_domain(struct domain *d, struct dt_device_node *dev,
>> + bool need_mapping,
>> + struct rangeset *irq_ranges);
>> +
>> #endif /* __XEN_FDT_DOMAIN_BUILD_H__ */
>>
>> /*
Thanks.
~ Oleksii
^ permalink raw reply
* [PATCH] drm/adp: Free FE IRQ on bind failure
From: Myeonghun Pak @ 2026-06-24 9:00 UTC (permalink / raw)
To: Sasha Finkelstein, Janne Grunau, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter
Cc: dri-devel, asahi, linux-kernel, Myeonghun Pak, Ijae Kim
adp_drm_bind() requests the front-end IRQ before registering the DRM
device. If drm_dev_register() fails, the function returns immediately
and leaves the IRQ handler registered.
Release the IRQ on the drm_dev_register() error path. The normal unbind
path still frees the IRQ after successful registration.
Fixes: 332122eba628 ("drm: adp: Add Apple Display Pipe driver")
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/gpu/drm/adp/adp_drv.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/adp/adp_drv.c b/drivers/gpu/drm/adp/adp_drv.c
index 4554cf75565e..20f38543d04e 100644
--- a/drivers/gpu/drm/adp/adp_drv.c
+++ b/drivers/gpu/drm/adp/adp_drv.c
@@ -535,9 +535,13 @@ static int adp_drm_bind(struct device *dev)
err = drm_dev_register(&adp->drm, 0);
if (err)
- return err;
+ goto err_free_irq;
return 0;
+
+err_free_irq:
+ free_irq(adp->fe_irq, adp);
+ return err;
}
static void adp_drm_unbind(struct device *dev)
--
2.47.1
^ permalink raw reply related
* Re: [f2fs-dev] [PATCH v14 00/15] Exposing case folding behavior
From: patchwork-bot+f2fs--- via Linux-f2fs-devel @ 2026-06-24 8:59 UTC (permalink / raw)
To: Chuck Lever
Cc: jack, pc, yuezhang.mo, cem, roland.mainz, almaz.alexandrovich,
adilger.kernel, linux-cifs, slava, djwong, linux-ext4, linkinjeon,
sprasad, frank.li, linux-nfs, viro, ronniesahlberg, glaubitz,
jaegeuk, linux-xfs, hirofumi, brauner, tytso, linux-api,
linux-f2fs-devel, sfrench, senozhatsky, chuck.lever, hansg, anna,
linux-fsdevel, sj1557.seo, trondmy, stfrench
In-Reply-To: <20260507-case-sensitivity-v14-0-e62cc8200435@oracle.com>
Hello:
This series was applied to jaegeuk/f2fs.git (dev)
by Christian Brauner <brauner@kernel.org>:
On Thu, 07 May 2026 04:52:53 -0400 you wrote:
> Christian, let's lock this one in. I will post subsequent changes
> as delta patches.
>
> Following on from:
>
> https://lore.kernel.org/linux-nfs/20251021-zypressen-bazillus-545a44af57fd@brauner/T/#m0ba197d75b7921d994cf284f3cef3a62abb11aaa
>
> [...]
Here is the summary with links:
- [f2fs-dev,v14,01/15] fs: Move file_kattr initialization to callers
https://git.kernel.org/jaegeuk/f2fs/c/14c3197ecf07
- [f2fs-dev,v14,02/15] fs: Add case sensitivity flags to file_kattr
https://git.kernel.org/jaegeuk/f2fs/c/3035e4454142
- [f2fs-dev,v14,03/15] fat: Implement fileattr_get for case sensitivity
https://git.kernel.org/jaegeuk/f2fs/c/c92db2ca726f
- [f2fs-dev,v14,04/15] exfat: Implement fileattr_get for case sensitivity
https://git.kernel.org/jaegeuk/f2fs/c/27e0b573dd4a
- [f2fs-dev,v14,05/15] ntfs3: Implement fileattr_get for case sensitivity
https://git.kernel.org/jaegeuk/f2fs/c/eeb7b37b9700
- [f2fs-dev,v14,06/15] hfs: Implement fileattr_get for case sensitivity
https://git.kernel.org/jaegeuk/f2fs/c/b6fe046c3023
- [f2fs-dev,v14,07/15] hfsplus: Report case sensitivity in fileattr_get
https://git.kernel.org/jaegeuk/f2fs/c/a6469a15eefe
- [f2fs-dev,v14,08/15] xfs: Report case sensitivity in fileattr_get
https://git.kernel.org/jaegeuk/f2fs/c/c9da43e4e5c3
- [f2fs-dev,v14,09/15] cifs: Implement fileattr_get for case sensitivity
https://git.kernel.org/jaegeuk/f2fs/c/e50bc12f5a36
- [f2fs-dev,v14,10/15] nfs: Implement fileattr_get for case sensitivity
https://git.kernel.org/jaegeuk/f2fs/c/92d67628a1a9
- [f2fs-dev,v14,11/15] vboxsf: Implement fileattr_get for case sensitivity
https://git.kernel.org/jaegeuk/f2fs/c/ef14aa143f1d
- [f2fs-dev,v14,12/15] isofs: Implement fileattr_get for case sensitivity
https://git.kernel.org/jaegeuk/f2fs/c/7bbd51b1d748
- [f2fs-dev,v14,13/15] nfsd: Report export case-folding via NFSv3 PATHCONF
https://git.kernel.org/jaegeuk/f2fs/c/211cb2ba4877
- [f2fs-dev,v14,14/15] nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and FATTR4_CASE_PRESERVING
https://git.kernel.org/jaegeuk/f2fs/c/01ee7c3d2e23
- [f2fs-dev,v14,15/15] ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION
https://git.kernel.org/jaegeuk/f2fs/c/0164df1d1de7
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply
* [f2fs-dev] Patchwork summary for: f2fs
From: patchwork-bot+f2fs--- via Linux-f2fs-devel @ 2026-06-24 8:59 UTC (permalink / raw)
To: linux-f2fs-devel
Hello:
The following patches were marked "accepted", because they were applied to
jaegeuk/f2fs.git (dev):
Series: Exposing case folding behavior
Submitter: Chuck Lever <cel@kernel.org>
Committer: Christian Brauner <brauner@kernel.org>
Patchwork: https://patchwork.kernel.org/project/f2fs/list/?series=1090897
Lore link: https://lore.kernel.org/r/20260507-case-sensitivity-v14-0-e62cc8200435@oracle.com
Patches: [f2fs-dev,v14,01/15] fs: Move file_kattr initialization to callers
[f2fs-dev,v14,02/15] fs: Add case sensitivity flags to file_kattr
[f2fs-dev,v14,03/15] fat: Implement fileattr_get for case sensitivity
[f2fs-dev,v14,04/15] exfat: Implement fileattr_get for case sensitivity
[f2fs-dev,v14,05/15] ntfs3: Implement fileattr_get for case sensitivity
[f2fs-dev,v14,06/15] hfs: Implement fileattr_get for case sensitivity
[f2fs-dev,v14,07/15] hfsplus: Report case sensitivity in fileattr_get
[f2fs-dev,v14,08/15] xfs: Report case sensitivity in fileattr_get
[f2fs-dev,v14,09/15] cifs: Implement fileattr_get for case sensitivity
[f2fs-dev,v14,10/15] nfs: Implement fileattr_get for case sensitivity
[f2fs-dev,v14,11/15] vboxsf: Implement fileattr_get for case sensitivity
[f2fs-dev,v14,12/15] isofs: Implement fileattr_get for case sensitivity
[f2fs-dev,v14,13/15] nfsd: Report export case-folding via NFSv3 PATHCONF
[f2fs-dev,v14,14/15] nfsd: Implement NFSv4 FATTR4_CASE_INSENSITIVE and FATTR4_CASE_PRESERVING
[f2fs-dev,v14,15/15] ksmbd: Report filesystem case sensitivity via FS_ATTRIBUTE_INFORMATION
Series: fs-verity support for XFS with post EOF merkle tree
Submitter: Andrey Albershteyn <aalbersh@kernel.org>
Patchwork: https://patchwork.kernel.org/project/f2fs/list/?series=1098004
Lore link: https://lore.kernel.org/r/20260520123722.405752-1-aalbersh@kernel.org
Patches: [f2fs-dev,v10,01/22] fsverity: report validation errors through fserror to fsnotify
[f2fs-dev,v10,04/22] fsverity: generate and store zero-block hash
[f2fs-dev,v10,07/22] iomap: introduce IOMAP_F_FSVERITY and teach writeback to handle fsverity
[f2fs-dev,v10,08/22] iomap: teach iomap to read files with fsverity
[f2fs-dev,v10,09/22] iomap: introduce iomap_fsverity_write() for writing fsverity metadata
Series: [f2fs-dev,v9,01/22] fsverity: report validation errors through fserror to fsnotify
Submitter: Andrey Albershteyn <aalbersh@kernel.org>
Patchwork: https://patchwork.kernel.org/project/f2fs/list/?series=1086679
Lore link: https://lore.kernel.org/r/20260428083332.768693-2-aalbersh@kernel.org
Patches: [f2fs-dev,v9,01/22] fsverity: report validation errors through fserror to fsnotify
[f2fs-dev,v9,04/22] fsverity: generate and store zero-block hash
[f2fs-dev,v9,09/22] iomap: introduce iomap_fsverity_write() for writing fsverity metadata
Patch: [f2fs-dev,GIT,PULL] f2fs update for 7.2-rc1
Submitter: Jaegeuk Kim <jaegeuk@kernel.org>
Committer: Linus Torvalds <torvalds@linux-foundation.org>
Patchwork: https://patchwork.kernel.org/project/f2fs/list/?series=1115531
Lore link: https://lore.kernel.org/r/ajrLmn16uMPcc4Lv@google.com
Series: Subject: Exposing case folding behavior
Submitter: Chuck Lever <cel@kernel.org>
Patchwork: https://patchwork.kernel.org/project/f2fs/list/?series=1055004
Lore link: https://lore.kernel.org/r/20260217214741.1928576-1-cel@kernel.org
Patches: [f2fs-dev,v8,01/17] fs: Move file_kattr initialization to callers
[f2fs-dev,v8,02/17] fs: Add case sensitivity flags to file_kattr
Total patches: 26
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.