| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/06/29 13:13 | flow | patch-triage |
3mArgs:null Results: {
"EnableConfigs": [
"RUST",
"SAMPLES_RUST",
"SAMPLE_RUST_DMA",
"SAMPLE_RUST_DRIVER_I2C",
"SAMPLE_RUST_I2C_CLIENT",
"SAMPLE_RUST_DRIVER_PCI",
"SAMPLE_RUST_DRIVER_PLATFORM",
"SAMPLE_RUST_DRIVER_USB",
"SAMPLE_RUST_DRIVER_AUXILIARY",
"SAMPLE_RUST_SOC",
"DRM_NOVA",
"DRM_TYR",
"NOVA_CORE",
"PWM_TH1520",
"CPUFREQ_DT_RUST",
"AX88796B_RUST_PHY",
"AMCC_QT2025_PHY"
],
"FocusSymbols": [],
"Reasoning": "The patch modifies core Rust abstractions for device drivers (PCI, USB, Platform, I2C, Auxiliary, ACPI, OF), changing how device ID tables are generated and how match data is retrieved during driver probe. Fuzzing is needed to ensure Rust drivers can still probe successfully and receive correct match data.",
"WorthFuzzing": true
} |
| 1/1 | 2026/06/29 13:13 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 1f3cc9a5a864751ea4393bef6c3e8486f48b1a6b\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Jun 29 13:13:08 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/MAINTAINERS b/MAINTAINERS\nindex 15011f5752a994..07240e0b745180 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -297,7 +297,6 @@ F:\tinclude/linux/acpi.h\n F:\tinclude/linux/fwnode.h\n F:\tinclude/linux/fw_table.h\n F:\tlib/fw_table.c\n-F:\trust/helpers/acpi.c\n F:\trust/kernel/acpi.rs\n F:\ttools/power/acpi/\n \ndiff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c\nindex a30a904f6535f4..1fb0b10bf92479 100644\n--- a/drivers/acpi/bus.c\n+++ b/drivers/acpi/bus.c\n@@ -898,9 +898,9 @@ const struct acpi_device *acpi_companion_match(const struct device *dev)\n * identifiers and a _DSD object with the \"compatible\" property, use that\n * property to match against the given list of identifiers.\n */\n-bool acpi_of_match_device(const struct acpi_device *adev,\n-\t\t\t const struct of_device_id *of_match_table,\n-\t\t\t const struct of_device_id **of_id)\n+static bool acpi_of_match_device(const struct acpi_device *adev,\n+\t\t\t\t const struct of_device_id *of_match_table,\n+\t\t\t\t const struct of_device_id **of_id)\n {\n \tconst union acpi_object *of_compatible, *obj;\n \tint i, nval;\ndiff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs\nindex 10106fa13095e4..145daa12072f49 100644\n--- a/drivers/cpufreq/rcpufreq_dt.rs\n+++ b/drivers/cpufreq/rcpufreq_dt.rs\n@@ -194,7 +194,6 @@ fn register_em(policy: \u0026mut cpufreq::Policy) {\n \n kernel::of_device_table!(\n OF_TABLE,\n- MODULE_OF_TABLE,\n \u003cCPUFreqDTDriver as platform::Driver\u003e::IdInfo,\n [(of::DeviceId::new(c\"operating-points-v2\"), ())]\n );\ndiff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs\nindex 48933d86ddda9b..43f15cdfeb09b3 100644\n--- a/drivers/gpu/drm/nova/driver.rs\n+++ b/drivers/gpu/drm/nova/driver.rs\n@@ -43,7 +43,6 @@ pub(crate) struct NovaData {\n \n kernel::auxiliary_device_table!(\n AUX_TABLE,\n- MODULE_AUX_TABLE,\n \u003cNovaDriver as auxiliary::Driver\u003e::IdInfo,\n [(\n auxiliary::DeviceId::new(NOVA_CORE_MODULE_NAME, AUXILIARY_NAME),\ndiff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs\nindex d063bc664cc117..218e9af899c7c7 100644\n--- a/drivers/gpu/drm/tyr/driver.rs\n+++ b/drivers/gpu/drm/tyr/driver.rs\n@@ -87,7 +87,6 @@ fn issue_soft_reset(dev: \u0026Device, iomem: \u0026IoMem\u003c'_\u003e) -\u003e Result {\n \n kernel::of_device_table!(\n OF_TABLE,\n- MODULE_OF_TABLE,\n \u003cTyrPlatformDriver as platform::Driver\u003e::IdInfo,\n [\n (of::DeviceId::new(c\"rockchip,rk3588-mali\"), ()),\ndiff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs\nindex 5738d4ac521b72..0c53b7239ac9e9 100644\n--- a/drivers/gpu/nova-core/driver.rs\n+++ b/drivers/gpu/nova-core/driver.rs\n@@ -40,7 +40,6 @@ pub(crate) struct NovaCore\u003c'bound\u003e {\n \n kernel::pci_device_table!(\n PCI_TABLE,\n- MODULE_PCI_TABLE,\n \u003cNovaCoreDriver as pci::Driver\u003e::IdInfo,\n [\n // Modern NVIDIA GPUs will show up as either VGA or 3D controllers.\n@@ -70,7 +69,7 @@ impl pci::Driver for NovaCoreDriver {\n \n fn probe\u003c'bound\u003e(\n pdev: \u0026'bound pci::Device\u003cCore\u003c'_\u003e\u003e,\n- _info: \u0026'bound Self::IdInfo,\n+ _info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n ) -\u003e impl PinInit\u003cSelf::Data\u003c'bound\u003e, Error\u003e + 'bound {\n pin_init::pin_init_scope(move || {\n dev_dbg!(pdev, \"Probe Nova Core GPU driver.\\n\");\ndiff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs\nindex 3e3fa51ccef911..1df752330e8fd9 100644\n--- a/drivers/pwm/pwm_th1520.rs\n+++ b/drivers/pwm/pwm_th1520.rs\n@@ -303,7 +303,6 @@ fn drop(self: Pin\u003c\u0026mut Self\u003e) {\n \n kernel::of_device_table!(\n OF_TABLE,\n- MODULE_OF_TABLE,\n \u003cTh1520PwmPlatformDriver as platform::Driver\u003e::IdInfo,\n [(of::DeviceId::new(c\"thead,th1520-pwm\"), ())]\n );\ndiff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h\nindex 714d111d80530f..7e57f9698f7ced 100644\n--- a/include/acpi/acpi_bus.h\n+++ b/include/acpi/acpi_bus.h\n@@ -189,10 +189,6 @@ struct acpi_driver {\n * -----------\n */\n \n-bool acpi_of_match_device(const struct acpi_device *adev,\n-\t\t\t const struct of_device_id *of_match_table,\n-\t\t\t const struct of_device_id **of_id);\n-\n /* Status (_STA) */\n \n struct acpi_device_status {\n@@ -1000,13 +996,6 @@ int acpi_scan_add_dep(acpi_handle handle, struct acpi_handle_list *dep_devices);\n u32 arch_acpi_add_auto_dep(acpi_handle handle);\n #else\t/* CONFIG_ACPI */\n \n-static inline bool acpi_of_match_device(const struct acpi_device *adev,\n-\t\t\t\t\tconst struct of_device_id *of_match_table,\n-\t\t\t\t\tconst struct of_device_id **of_id)\n-{\n-\treturn false;\n-}\n-\n static inline int register_acpi_bus_type(void *bus) { return 0; }\n static inline int unregister_acpi_bus_type(void *bus) { return 0; }\n \ndiff --git a/rust/helpers/acpi.c b/rust/helpers/acpi.c\ndeleted file mode 100644\nindex e75c9807bbadcc..00000000000000\n--- a/rust/helpers/acpi.c\n+++ /dev/null\n@@ -1,16 +0,0 @@\n-// SPDX-License-Identifier: GPL-2.0\n-\n-#include \u003clinux/acpi.h\u003e\n-#include \u003cacpi/acpi_bus.h\u003e\n-\n-__rust_helper bool rust_helper_acpi_of_match_device(const struct acpi_device *adev,\n-\t\t\t\t\t\t const struct of_device_id *of_match_table,\n-\t\t\t\t\t\t const struct of_device_id **of_id)\n-{\n-\treturn acpi_of_match_device(adev, of_match_table, of_id);\n-}\n-\n-__rust_helper struct acpi_device *rust_helper_to_acpi_device_node(struct fwnode_handle *fwnode)\n-{\n-\treturn to_acpi_device_node(fwnode);\n-}\ndiff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c\nindex 998e31052e6601..fadd7acdd81c93 100644\n--- a/rust/helpers/helpers.c\n+++ b/rust/helpers/helpers.c\n@@ -38,7 +38,6 @@\n #define __rust_helper __always_inline\n #endif\n \n-#include \"acpi.c\"\n #include \"atomic.c\"\n #include \"atomic_ext.c\"\n #include \"auxiliary.c\"\ndiff --git a/rust/kernel/acpi.rs b/rust/kernel/acpi.rs\nindex 9b8efa623130c1..ea2ce61ee3931f 100644\n--- a/rust/kernel/acpi.rs\n+++ b/rust/kernel/acpi.rs\n@@ -25,10 +25,6 @@ unsafe impl RawDeviceId for DeviceId {\n // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.\n unsafe impl RawDeviceIdIndex for DeviceId {\n const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::acpi_device_id, driver_data);\n-\n- fn index(\u0026self) -\u003e usize {\n- self.0.driver_data\n- }\n }\n \n impl DeviceId {\n@@ -53,13 +49,7 @@ pub const fn new(id: \u0026'static CStr) -\u003e Self {\n /// Create an ACPI `IdTable` with an \"alias\" for modpost.\n #[macro_export]\n macro_rules! acpi_device_table {\n- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) =\u003e {\n- const $table_name: $crate::device_id::IdArray\u003c\n- $crate::acpi::DeviceId,\n- $id_info_type,\n- { $table_data.len() },\n- \u003e = $crate::device_id::IdArray::new($table_data);\n-\n- $crate::module_device_table!(\"acpi\", $module_table_name, $table_name);\n+ ($($tt:tt)*) =\u003e {\n+ $crate::module_device_table!(\"acpi\", $crate::acpi::DeviceId, $($tt)*);\n };\n }\ndiff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs\nindex c42928d5a2393f..aa13d8866a1964 100644\n--- a/rust/kernel/auxiliary.rs\n+++ b/rust/kernel/auxiliary.rs\n@@ -93,7 +93,9 @@ extern \"C\" fn probe_callback(\n // SAFETY: `DeviceId` is a `#[repr(transparent)`] wrapper of `struct auxiliary_device_id`\n // and does not add additional invariants, so it's safe to transmute.\n let id = unsafe { \u0026*id.cast::\u003cDeviceId\u003e() };\n- let info = T::ID_TABLE.info(id.index());\n+\n+ // SAFETY: `id` comes from `T::ID_TABLE` which is of type `IdArray\u003c_, T::IdInfo\u003e`.\n+ let info = unsafe { id.info_unchecked::\u003cT::IdInfo\u003e() };\n \n from_result(|| {\n let data = T::probe(adev, info);\n@@ -169,10 +171,6 @@ unsafe impl RawDeviceId for DeviceId {\n unsafe impl RawDeviceIdIndex for DeviceId {\n const DRIVER_DATA_OFFSET: usize =\n core::mem::offset_of!(bindings::auxiliary_device_id, driver_data);\n-\n- fn index(\u0026self) -\u003e usize {\n- self.0.driver_data\n- }\n }\n \n /// IdTable type for auxiliary drivers.\n@@ -181,14 +179,8 @@ fn index(\u0026self) -\u003e usize {\n /// Create a auxiliary `IdTable` with its alias for modpost.\n #[macro_export]\n macro_rules! auxiliary_device_table {\n- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) =\u003e {\n- const $table_name: $crate::device_id::IdArray\u003c\n- $crate::auxiliary::DeviceId,\n- $id_info_type,\n- { $table_data.len() },\n- \u003e = $crate::device_id::IdArray::new($table_data);\n-\n- $crate::module_device_table!(\"auxiliary\", $module_table_name, $table_name);\n+ ($($tt:tt)*) =\u003e {\n+ $crate::module_device_table!(\"auxiliary\", $crate::auxiliary::DeviceId, $($tt)*);\n };\n }\n \ndiff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs\nindex 8e97214460146e..5f4d191fce515a 100644\n--- a/rust/kernel/device_id.rs\n+++ b/rust/kernel/device_id.rs\n@@ -5,7 +5,10 @@\n //! Each bus / subsystem that matches device and driver through a bus / subsystem specific ID is\n //! expected to implement [`RawDeviceId`].\n \n-use core::mem::MaybeUninit;\n+use core::{\n+ marker::PhantomData,\n+ mem::MaybeUninit, //\n+};\n \n /// Marker trait to indicate a Rust device ID type represents a corresponding C device ID type.\n ///\n@@ -47,112 +50,110 @@ pub unsafe trait RawDeviceIdIndex: RawDeviceId {\n /// The offset (in bytes) to the context/data field in the raw device ID.\n const DRIVER_DATA_OFFSET: usize;\n \n- /// The index stored at `DRIVER_DATA_OFFSET` of the implementor of the [`RawDeviceIdIndex`]\n- /// trait.\n- fn index(\u0026self) -\u003e usize;\n-}\n-\n-/// A zero-terminated device id array.\n-#[repr(C)]\n-pub struct RawIdArray\u003cT: RawDeviceId, const N: usize\u003e {\n- ids: [T::RawType; N],\n- sentinel: MaybeUninit\u003cT::RawType\u003e,\n-}\n+ /// Obtain the data pointer stored inside the device ID.\n+ ///\n+ /// # Safety\n+ ///\n+ /// `\u0026Self` must be stored inside a `IdArray\u003cSelf, U\u003e`.\n+ unsafe fn info_unchecked\u003cU\u003e(\u0026self) -\u003e \u0026'static U {\n+ // SAFETY: By safety requirement of the trait, this is `self.driver_data as *const U` and by\n+ // the safety requirement of the function, this is stored in `IdArray\u003cSelf, U\u003e` so is\n+ // convertible to `\u0026'static U`.\n+ unsafe {\n+ core::ptr::from_ref(self)\n+ .byte_add(Self::DRIVER_DATA_OFFSET)\n+ .cast::\u003c\u0026U\u003e()\n+ .read()\n+ }\n+ }\n \n-impl\u003cT: RawDeviceId, const N: usize\u003e RawIdArray\u003cT, N\u003e {\n- #[doc(hidden)]\n- pub const fn size(\u0026self) -\u003e usize {\n- core::mem::size_of::\u003cSelf\u003e()\n+ /// Obtain the data pointer stored inside the device ID.\n+ ///\n+ /// # Safety\n+ ///\n+ /// `\u0026Self` must be stored inside a `IdArray\u003cSelf, U\u003e`, or has NULL (or 0) as driver data.\n+ unsafe fn info_unchecked_opt\u003cU\u003e(\u0026self) -\u003e Option\u003c\u0026'static U\u003e {\n+ // SAFETY: By safety requirement of the trait, this is `self.driver_data as *const U` and by\n+ // the safety requirement of the function, if this is stored in `IdArray\u003cSelf, U\u003e`, this is\n+ // convertible to `Option\u003c\u0026'static U\u003e`. Otherwise it is NULL which is `None` as\n+ // `Option\u003c\u0026U\u003e`.\n+ unsafe {\n+ core::ptr::from_ref(self)\n+ .byte_add(Self::DRIVER_DATA_OFFSET)\n+ .cast::\u003cOption\u003c\u0026U\u003e\u003e()\n+ .read()\n+ }\n }\n }\n \n /// A zero-terminated device id array, followed by context data.\n #[repr(C)]\n-pub struct IdArray\u003cT: RawDeviceId, U, const N: usize\u003e {\n- raw_ids: RawIdArray\u003cT, N\u003e,\n- id_infos: [U; N],\n+pub struct IdArray\u003cT: RawDeviceId, U: 'static, const N: usize\u003e {\n+ // This is `MaybeUninit\u003cT::RawType\u003e` so any bytes inside it can carry provenance in CTFE.\n+ // If this were `T::RawType`, integer fields would not be able to contain pointers.\n+ ids: [MaybeUninit\u003cT::RawType\u003e; N],\n+ sentinel: MaybeUninit\u003cT::RawType\u003e,\n+ phantom: PhantomData\u003c\u0026'static U\u003e,\n }\n \n-impl\u003cT: RawDeviceId, U, const N: usize\u003e IdArray\u003cT, U, N\u003e {\n+// SAFETY: device ID is plain data plus a `\u0026'static U` and can thus be sent between threads safely\n+// if `\u0026U` can.\n+unsafe impl\u003cT: RawDeviceId, U: Sync + 'static, const N: usize\u003e Send for IdArray\u003cT, U, N\u003e {}\n+\n+// SAFETY: device ID is plain data plus a `\u0026'static U` and can thus be shared between threads safely\n+// if `\u0026U` can.\n+unsafe impl\u003cT: RawDeviceId, U: Sync + 'static, const N: usize\u003e Sync for IdArray\u003cT, U, N\u003e {}\n+\n+impl\u003cT: RawDeviceId + RawDeviceIdIndex, U: 'static, const N: usize\u003e IdArray\u003cT, U, N\u003e {\n /// Creates a new instance of the array.\n ///\n /// The contents are derived from the given identifiers and context information.\n- ///\n- /// # Safety\n- ///\n- /// `data_offset` as `None` is always safe.\n- /// If `data_offset` is `Some(data_offset)`, then:\n- /// - `data_offset` must be the correct offset (in bytes) to the context/data field\n- /// (e.g., the `driver_data` field) within the raw device ID structure.\n- /// - The field at `data_offset` must be correctly sized to hold a `usize`.\n- const unsafe fn build(ids: [(T, U); N], data_offset: Option\u003cusize\u003e) -\u003e Self {\n+ pub const fn new(ids: [(T, \u0026'static U); N]) -\u003e Self {\n let mut raw_ids = [const { MaybeUninit::\u003cT::RawType\u003e::uninit() }; N];\n- let mut infos = [const { MaybeUninit::uninit() }; N];\n \n let mut i = 0usize;\n while i \u003c N {\n // SAFETY: by the safety requirement of `RawDeviceId`, we're guaranteed that `T` is\n // layout-wise compatible with `RawType`.\n raw_ids[i] = unsafe { core::mem::transmute_copy(\u0026ids[i].0) };\n- if let Some(data_offset) = data_offset {\n- // SAFETY: by the safety requirement of this function, this would be effectively\n- // `raw_ids[i].driver_data = i;`.\n- unsafe {\n- raw_ids[i]\n- .as_mut_ptr()\n- .byte_add(data_offset)\n- .cast::\u003cusize\u003e()\n- .write(i);\n- }\n+ // SAFETY: by the safety requirement of `RawDeviceIdIndex`, this would be effectively\n+ // `raw_ids[i].driver_data = ids[i].1;`.\n+ unsafe {\n+ raw_ids[i]\n+ .as_mut_ptr()\n+ .byte_add(T::DRIVER_DATA_OFFSET)\n+ .cast::\u003c\u0026U\u003e()\n+ .write(ids[i].1);\n }\n \n- // SAFETY: this is effectively a move: `infos[i] = ids[i].1`. We make a copy here but\n- // later forget `ids`.\n- infos[i] = MaybeUninit::new(unsafe { core::ptr::read(\u0026ids[i].1) });\n i += 1;\n }\n \n core::mem::forget(ids);\n \n Self {\n- raw_ids: RawIdArray {\n- // SAFETY: this is effectively `array_assume_init`, which is unstable, so we use\n- // `transmute_copy` instead. We have initialized all elements of `raw_ids` so this\n- // `array_assume_init` is safe.\n- ids: unsafe { core::mem::transmute_copy(\u0026raw_ids) },\n- sentinel: MaybeUninit::zeroed(),\n- },\n- // SAFETY: We have initialized all elements of `infos` so this `array_assume_init` is\n- // safe.\n- id_infos: unsafe { core::mem::transmute_copy(\u0026infos) },\n+ ids: raw_ids,\n+ sentinel: MaybeUninit::zeroed(),\n+ phantom: PhantomData,\n }\n }\n+}\n \n+impl\u003cT: RawDeviceId, const N: usize\u003e IdArray\u003cT, (), N\u003e {\n /// Creates a new instance of the array without writing index values.\n ///\n /// The contents are derived from the given identifiers and context information.\n /// If the device implements [`RawDeviceIdIndex`], consider using [`IdArray::new`] instead.\n- pub const fn new_without_index(ids: [(T, U); N]) -\u003e Self {\n- // SAFETY: Calling `Self::build` with `offset = None` is always safe,\n- // because no raw memory writes are performed in this case.\n- unsafe { Self::build(ids, None) }\n- }\n-\n- /// Reference to the contained [`RawIdArray`].\n- pub const fn raw_ids(\u0026self) -\u003e \u0026RawIdArray\u003cT, N\u003e {\n- \u0026self.raw_ids\n- }\n-}\n+ pub const fn new_without_index(ids: [T; N]) -\u003e Self {\n+ // SAFETY: `T` is layout-wise compatible with `T::RawType`, so is the array of them.\n+ let raw_ids: [MaybeUninit\u003cT::RawType\u003e; N] = unsafe { core::mem::transmute_copy(\u0026ids) };\n+ core::mem::forget(ids);\n \n-impl\u003cT: RawDeviceId + RawDeviceIdIndex, U, const N: usize\u003e IdArray\u003cT, U, N\u003e {\n- /// Creates a new instance of the array.\n- ///\n- /// The contents are derived from the given identifiers and context information.\n- pub const fn new(ids: [(T, U); N]) -\u003e Self {\n- // SAFETY: by the safety requirement of `RawDeviceIdIndex`,\n- // `T::DRIVER_DATA_OFFSET` is guaranteed to be the correct offset (in bytes) to\n- // a field within `T::RawType`.\n- unsafe { Self::build(ids, Some(T::DRIVER_DATA_OFFSET)) }\n+ Self {\n+ ids: raw_ids,\n+ sentinel: MaybeUninit::zeroed(),\n+ phantom: PhantomData,\n+ }\n }\n }\n \n@@ -165,12 +166,6 @@ impl\u003cT: RawDeviceId + RawDeviceIdIndex, U, const N: usize\u003e IdArray\u003cT, U, N\u003e {\n pub trait IdTable\u003cT: RawDeviceId, U\u003e {\n /// Obtain the pointer to the ID table.\n fn as_ptr(\u0026self) -\u003e *const T::RawType;\n-\n- /// Obtain the pointer to the bus specific device ID from an index.\n- fn id(\u0026self, index: usize) -\u003e \u0026T::RawType;\n-\n- /// Obtain the pointer to the driver-specific information from an index.\n- fn info(\u0026self, index: usize) -\u003e \u0026U;\n }\n \n impl\u003cT: RawDeviceId, U, const N: usize\u003e IdTable\u003cT, U\u003e for IdArray\u003cT, U, N\u003e {\n@@ -179,28 +174,56 @@ fn as_ptr(\u0026self) -\u003e *const T::RawType {\n // to access the sentinel.\n core::ptr::from_ref(self).cast()\n }\n-\n- fn id(\u0026self, index: usize) -\u003e \u0026T::RawType {\n- \u0026self.raw_ids.ids[index]\n- }\n-\n- fn info(\u0026self, index: usize) -\u003e \u0026U {\n- \u0026self.id_infos[index]\n- }\n }\n \n /// Create device table alias for modpost.\n #[macro_export]\n macro_rules! module_device_table {\n- ($table_type: literal, $module_table_name:ident, $table_name:ident) =\u003e {\n- #[rustfmt::skip]\n+ (\n+ $table_type: literal, $device_id_ty: ty,\n+ $table_name: ident, $id_info_type: ty,\n+ [$(($id: expr, $info:expr $(,)?)),* $(,)?]\n+ ) =\u003e {\n+ $crate::module_device_table!(\n+ $table_type, $device_id_ty, $table_name, $id_info_type,\n+ {$($id=\u003e$info,)*}\n+ );\n+ };\n+\n+ (\n+ $table_type: literal, $device_id_ty: ty,\n+ $table_name: ident, $id_info_type: ty,\n+ {$($id: expr =\u003e $info:expr),* $(,)?}\n+ ) =\u003e {\n+ #[export_name =\n+ concat!(\"__mod_device_table__\", ::core::line!(),\n+ \"__kmod_\", module_path!(),\n+ \"__\", $table_type,\n+ \"__\", stringify!($table_name))\n+ ]\n+ static $table_name: $crate::device_id::IdArray\u003c\n+ $device_id_ty,\n+ $id_info_type,\n+ { \u003c[$device_id_ty]\u003e::len(\u0026[$($id,)*]) },\n+ \u003e = $crate::device_id::IdArray::new([$(($id, \u0026$info),)*]);\n+ };\n+\n+ // Case for no ID info.\n+ (\n+ $table_type: literal, $device_id_ty: ty,\n+ $table_name: ident, @none,\n+ [$($id: expr),* $(,)?]\n+ ) =\u003e {\n #[export_name =\n- concat!(\"__mod_device_table__\", line!(),\n+ concat!(\"__mod_device_table__\", ::core::line!(),\n \"__kmod_\", module_path!(),\n \"__\", $table_type,\n \"__\", stringify!($table_name))\n ]\n- static $module_table_name: [::core::mem::MaybeUninit\u003cu8\u003e; $table_name.raw_ids().size()] =\n- unsafe { ::core::mem::transmute_copy($table_name.raw_ids()) };\n+ static $table_name: $crate::device_id::IdArray\u003c\n+ $device_id_ty,\n+ (),\n+ { \u003c[$device_id_ty]\u003e::len(\u0026[$($id,)*]) },\n+ \u003e = $crate::device_id::IdArray::new_without_index([$($id),*]);\n };\n }\ndiff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs\nindex bf5ba0d27553ed..c9c74c4dde8fa7 100644\n--- a/rust/kernel/driver.rs\n+++ b/rust/kernel/driver.rs\n@@ -291,26 +291,6 @@ fn init(\n }\n }\n \n-// Calling the FFI function directly from the `Adapter` impl may result in it being called\n-// directly from driver modules. This happens since the Rust compiler will use monomorphisation, so\n-// it might happen that functions are instantiated within the calling driver module. For now, work\n-// around this with `#[inline(never)]` helpers.\n-//\n-// TODO: Remove once a more generic solution has been implemented. For instance, we may be able to\n-// leverage `bindgen` to take care of this depending on whether a symbol is (already) exported.\n-#[inline(never)]\n-#[allow(clippy::missing_safety_doc)]\n-#[allow(dead_code)]\n-#[must_use]\n-unsafe fn acpi_of_match_device(\n- adev: *const bindings::acpi_device,\n- of_match_table: *const bindings::of_device_id,\n- of_id: *mut *const bindings::of_device_id,\n-) -\u003e bool {\n- // SAFETY: Safety requirements are the same as `bindings::acpi_of_match_device`.\n- unsafe { bindings::acpi_of_match_device(adev, of_match_table, of_id) }\n-}\n-\n /// The bus independent adapter to match a drivers and a devices.\n ///\n /// This trait should be implemented by the bus specific adapter, which represents the connection\n@@ -324,118 +304,23 @@ pub trait Adapter {\n /// The [`acpi::IdTable`] of the corresponding driver\n fn acpi_id_table() -\u003e Option\u003cacpi::IdTable\u003cSelf::IdInfo\u003e\u003e;\n \n- /// Returns the driver's private data from the matching entry in the [`acpi::IdTable`], if any.\n- ///\n- /// If this returns `None`, it means there is no match with an entry in the [`acpi::IdTable`].\n- fn acpi_id_info(dev: \u0026device::Device) -\u003e Option\u003c\u0026'static Self::IdInfo\u003e {\n- #[cfg(not(CONFIG_ACPI))]\n- {\n- let _ = dev;\n- None\n- }\n-\n- #[cfg(CONFIG_ACPI)]\n- {\n- let table = Self::acpi_id_table()?;\n-\n- // SAFETY:\n- // - `table` has static lifetime, hence it's valid for read,\n- // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.\n- let raw_id = unsafe { bindings::acpi_match_device(table.as_ptr(), dev.as_raw()) };\n-\n- if raw_id.is_null() {\n- None\n- } else {\n- // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct acpi_device_id`\n- // and does not add additional invariants, so it's safe to transmute.\n- let id = unsafe { \u0026*raw_id.cast::\u003cacpi::DeviceId\u003e() };\n-\n- Some(table.info(\u003cacpi::DeviceId as crate::device_id::RawDeviceIdIndex\u003e::index(id)))\n- }\n- }\n- }\n-\n /// The [`of::IdTable`] of the corresponding driver.\n fn of_id_table() -\u003e Option\u003cof::IdTable\u003cSelf::IdInfo\u003e\u003e;\n \n- /// Returns the driver's private data from the matching entry in the [`of::IdTable`], if any.\n- ///\n- /// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`].\n- fn of_id_info(dev: \u0026device::Device) -\u003e Option\u003c\u0026'static Self::IdInfo\u003e {\n- let table = Self::of_id_table()?;\n-\n- #[cfg(not(any(CONFIG_OF, CONFIG_ACPI)))]\n- {\n- let _ = (dev, table);\n- }\n-\n- #[cfg(CONFIG_OF)]\n- {\n- // SAFETY:\n- // - `table` has static lifetime, hence it's valid for read,\n- // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.\n- let raw_id = unsafe { bindings::of_match_device(table.as_ptr(), dev.as_raw()) };\n-\n- if !raw_id.is_null() {\n- // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`\n- // and does not add additional invariants, so it's safe to transmute.\n- let id = unsafe { \u0026*raw_id.cast::\u003cof::DeviceId\u003e() };\n-\n- return Some(table.info(\n- \u003cof::DeviceId as crate::device_id::RawDeviceIdIndex\u003e::index(id),\n- ));\n- }\n- }\n-\n- #[cfg(CONFIG_ACPI)]\n- {\n- use core::ptr;\n- use device::property::FwNode;\n-\n- let mut raw_id = ptr::null();\n-\n- let fwnode = dev.fwnode().map_or(ptr::null_mut(), FwNode::as_raw);\n-\n- // SAFETY: `fwnode` is a pointer to a valid `fwnode_handle`. A null pointer will be\n- // passed through the function.\n- let adev = unsafe { bindings::to_acpi_device_node(fwnode) };\n-\n- // SAFETY:\n- // - `adev` is a valid pointer to `acpi_device` or is null. It is guaranteed to be\n- // valid as long as `dev` is alive.\n- // - `table` has static lifetime, hence it's valid for read.\n- if unsafe { acpi_of_match_device(adev, table.as_ptr(), \u0026raw mut raw_id) } {\n- // SAFETY:\n- // - the function returns true, therefore `raw_id` has been set to a pointer to a\n- // valid `of_device_id`.\n- // - `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`\n- // and does not add additional invariants, so it's safe to transmute.\n- let id = unsafe { \u0026*raw_id.cast::\u003cof::DeviceId\u003e() };\n-\n- return Some(table.info(\n- \u003cof::DeviceId as crate::device_id::RawDeviceIdIndex\u003e::index(id),\n- ));\n- }\n- }\n-\n- None\n- }\n-\n /// Returns the driver's private data from the matching entry of any of the ID tables, if any.\n ///\n /// If this returns `None`, it means that there is no match in any of the ID tables directly\n /// associated with a [`device::Device`].\n- fn id_info(dev: \u0026device::Device) -\u003e Option\u003c\u0026'static Self::IdInfo\u003e {\n- let id = Self::acpi_id_info(dev);\n- if id.is_some() {\n- return id;\n- }\n-\n- let id = Self::of_id_info(dev);\n- if id.is_some() {\n- return id;\n- }\n-\n- None\n+ ///\n+ /// # Safety\n+ ///\n+ /// The caller must ensure that the `dev` matched data is of type `Self::IdInfo`.\n+ #[inline]\n+ unsafe fn id_info(dev: \u0026device::Device) -\u003e Option\u003c\u0026'static Self::IdInfo\u003e {\n+ // SAFETY: `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.\n+ let data = unsafe { bindings::device_get_match_data(dev.as_raw()) };\n+\n+ // SAFETY: Per safety requirement, `data` is of type `Self::IdInfo`.\n+ unsafe { data.cast::\u003cSelf::IdInfo\u003e().as_ref() }\n }\n }\ndiff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs\nindex 624b971ca8b0b2..2d2191164e252c 100644\n--- a/rust/kernel/i2c.rs\n+++ b/rust/kernel/i2c.rs\n@@ -65,10 +65,6 @@ unsafe impl RawDeviceId for DeviceId {\n // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.\n unsafe impl RawDeviceIdIndex for DeviceId {\n const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::i2c_device_id, driver_data);\n-\n- fn index(\u0026self) -\u003e usize {\n- self.0.driver_data\n- }\n }\n \n /// IdTable type for I2C\n@@ -77,14 +73,8 @@ fn index(\u0026self) -\u003e usize {\n /// Create a I2C `IdTable` with its alias for modpost.\n #[macro_export]\n macro_rules! i2c_device_table {\n- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) =\u003e {\n- const $table_name: $crate::device_id::IdArray\u003c\n- $crate::i2c::DeviceId,\n- $id_info_type,\n- { $table_data.len() },\n- \u003e = $crate::device_id::IdArray::new($table_data);\n-\n- $crate::module_device_table!(\"i2c\", $module_table_name, $table_name);\n+ ($($tt:tt)*) =\u003e {\n+ $crate::module_device_table!(\"i2c\", $crate::i2c::DeviceId, $($tt)*);\n };\n }\n \n@@ -159,8 +149,10 @@ extern \"C\" fn probe_callback(idev: *mut bindings::i2c_client) -\u003e kernel::ffi::c_\n // INVARIANT: `idev` is valid for the duration of `probe_callback()`.\n let idev = unsafe { \u0026*idev.cast::\u003cI2cClient\u003cdevice::CoreInternal\u003c'_\u003e\u003e\u003e() };\n \n- let info =\n- Self::i2c_id_info(idev).or_else(|| \u003cSelf as driver::Adapter\u003e::id_info(idev.as_ref()));\n+ let info = Self::i2c_id_info(idev).or_else(|| {\n+ // SAFETY: `idev` matched data is of type `Self::IdInfo`.\n+ unsafe { \u003cSelf as driver::Adapter\u003e::id_info(idev.as_ref()) }\n+ });\n \n from_result(|| {\n let data = T::probe(idev, info);\n@@ -218,7 +210,8 @@ fn i2c_id_info(dev: \u0026I2cClient) -\u003e Option\u003c\u0026'static \u003cSelf as driver::Adapter\u003e::Id\n // does not add additional invariants, so it's safe to transmute.\n let id = unsafe { \u0026*raw_id.cast::\u003cDeviceId\u003e() };\n \n- Some(table.info(\u003cDeviceId as RawDeviceIdIndex\u003e::index(id)))\n+ // SAFETY: `id` comes from `table` which is of type `IdArray\u003c_, Self::IdInfo\u003e`.\n+ Some(unsafe { id.info_unchecked::\u003cT::IdInfo\u003e() })\n }\n }\n \n@@ -267,7 +260,6 @@ macro_rules! module_i2c_driver {\n ///\n /// kernel::acpi_device_table!(\n /// ACPI_TABLE,\n-/// MODULE_ACPI_TABLE,\n /// \u003cMyDriver as i2c::Driver\u003e::IdInfo,\n /// [\n /// (acpi::DeviceId::new(c\"LNUXBEEF\"), ())\n@@ -276,7 +268,6 @@ macro_rules! module_i2c_driver {\n ///\n /// kernel::i2c_device_table!(\n /// I2C_TABLE,\n-/// MODULE_I2C_TABLE,\n /// \u003cMyDriver as i2c::Driver\u003e::IdInfo,\n /// [\n /// (i2c::DeviceId::new(c\"rust_driver_i2c\"), ())\n@@ -285,7 +276,6 @@ macro_rules! module_i2c_driver {\n ///\n /// kernel::of_device_table!(\n /// OF_TABLE,\n-/// MODULE_OF_TABLE,\n /// \u003cMyDriver as i2c::Driver\u003e::IdInfo,\n /// [\n /// (of::DeviceId::new(c\"test,device\"), ())\ndiff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs\nindex 3ca99db5cccf22..1e86b901c391bd 100644\n--- a/rust/kernel/net/phy.rs\n+++ b/rust/kernel/net/phy.rs\n@@ -800,62 +800,6 @@ const fn as_int(\u0026self) -\u003e u32 {\n /// }\n /// # }\n /// ```\n-///\n-/// This expands to the following code:\n-///\n-/// ```ignore\n-/// use kernel::net::phy::{self, DeviceId};\n-/// use kernel::prelude::*;\n-///\n-/// struct Module {\n-/// _reg: ::kernel::net::phy::Registration,\n-/// }\n-///\n-/// module! {\n-/// type: Module,\n-/// name: \"rust_sample_phy\",\n-/// authors: [\"Rust for Linux Contributors\"],\n-/// description: \"Rust sample PHYs driver\",\n-/// license: \"GPL\",\n-/// }\n-///\n-/// struct PhySample;\n-///\n-/// #[vtable]\n-/// impl phy::Driver for PhySample {\n-/// const NAME: \u0026'static CStr = c\"PhySample\";\n-/// const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x00000001);\n-/// }\n-///\n-/// const _: () = {\n-/// static mut DRIVERS: [::kernel::net::phy::DriverVTable; 1] =\n-/// [::kernel::net::phy::create_phy_driver::\u003cPhySample\u003e()];\n-///\n-/// impl ::kernel::Module for Module {\n-/// fn init(module: \u0026'static ::kernel::ThisModule) -\u003e Result\u003cSelf\u003e {\n-/// let drivers = unsafe { \u0026mut DRIVERS };\n-/// let mut reg = ::kernel::net::phy::Registration::register(\n-/// module,\n-/// ::core::pin::Pin::static_mut(drivers),\n-/// )?;\n-/// Ok(Module { _reg: reg })\n-/// }\n-/// }\n-/// };\n-///\n-/// const N: usize = 1;\n-///\n-/// const TABLE: ::kernel::device_id::IdArray\u003c::kernel::net::phy::DeviceId, (), N\u003e =\n-/// ::kernel::device_id::IdArray::new_without_index([\n-/// ::kernel::net::phy::DeviceId(\n-/// ::kernel::bindings::mdio_device_id {\n-/// phy_id: 0x00000001,\n-/// phy_id_mask: 0xffffffff,\n-/// }),\n-/// ]);\n-///\n-/// ::kernel::module_device_table!(\"mdio\", phydev, TABLE);\n-/// ```\n #[macro_export]\n macro_rules! module_phy_driver {\n (@replace_expr $_t:tt $sub:expr) =\u003e {$sub};\n@@ -865,12 +809,10 @@ macro_rules! module_phy_driver {\n };\n \n (@device_table [$($dev:expr),+]) =\u003e {\n- const N: usize = $crate::module_phy_driver!(@count_devices $($dev),+);\n-\n- const TABLE: $crate::device_id::IdArray\u003c$crate::net::phy::DeviceId, (), N\u003e =\n- $crate::device_id::IdArray::new_without_index([ $(($dev,())),+, ]);\n-\n- $crate::module_device_table!(\"mdio\", phydev, TABLE);\n+ $crate::module_device_table!(\n+ \"mdio\", $crate::net::phy::DeviceId,\n+ TABLE, @none, [$($dev),+]\n+ );\n };\n \n (drivers: [$($driver:ident),+ $(,)?], device_table: [$($dev:expr),+ $(,)?], $($f:tt)*) =\u003e {\ndiff --git a/rust/kernel/of.rs b/rust/kernel/of.rs\nindex 58b20c367f993f..d0318f62afd7c8 100644\n--- a/rust/kernel/of.rs\n+++ b/rust/kernel/of.rs\n@@ -25,10 +25,6 @@ unsafe impl RawDeviceId for DeviceId {\n // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `data` field.\n unsafe impl RawDeviceIdIndex for DeviceId {\n const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::of_device_id, data);\n-\n- fn index(\u0026self) -\u003e usize {\n- self.0.data as usize\n- }\n }\n \n impl DeviceId {\n@@ -53,13 +49,7 @@ pub const fn new(compatible: \u0026'static CStr) -\u003e Self {\n /// Create an OF `IdTable` with an \"alias\" for modpost.\n #[macro_export]\n macro_rules! of_device_table {\n- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) =\u003e {\n- const $table_name: $crate::device_id::IdArray\u003c\n- $crate::of::DeviceId,\n- $id_info_type,\n- { $table_data.len() },\n- \u003e = $crate::device_id::IdArray::new($table_data);\n-\n- $crate::module_device_table!(\"of\", $module_table_name, $table_name);\n+ ($($tt:tt)*) =\u003e {\n+ $crate::module_device_table!(\"of\", $crate::of::DeviceId, $($tt)*);\n };\n }\ndiff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs\nindex 5071cae6543fd2..925cf280dae2a9 100644\n--- a/rust/kernel/pci.rs\n+++ b/rust/kernel/pci.rs\n@@ -110,7 +110,11 @@ extern \"C\" fn probe_callback(\n // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct pci_device_id` and\n // does not add additional invariants, so it's safe to transmute.\n let id = unsafe { \u0026*id.cast::\u003cDeviceId\u003e() };\n- let info = T::ID_TABLE.info(id.index());\n+\n+ // SAFETY: `id` comes from `T::ID_TABLE` which is of type `IdArray\u003c_, T::IdInfo\u003e` or\n+ // `pci_device_id_any` which has 0 as driver_data. It can also come from dynamic IDs, which\n+ // will ensure that `driver_data` exists in `T::ID_TABLE`.\n+ let info = unsafe { id.info_unchecked_opt::\u003cT::IdInfo\u003e() };\n \n from_result(|| {\n let data = T::probe(pdev, info);\n@@ -233,10 +237,6 @@ unsafe impl RawDeviceId for DeviceId {\n // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.\n unsafe impl RawDeviceIdIndex for DeviceId {\n const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data);\n-\n- fn index(\u0026self) -\u003e usize {\n- self.0.driver_data\n- }\n }\n \n /// `IdTable` type for PCI.\n@@ -245,14 +245,8 @@ fn index(\u0026self) -\u003e usize {\n /// Create a PCI `IdTable` with its alias for modpost.\n #[macro_export]\n macro_rules! pci_device_table {\n- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) =\u003e {\n- const $table_name: $crate::device_id::IdArray\u003c\n- $crate::pci::DeviceId,\n- $id_info_type,\n- { $table_data.len() },\n- \u003e = $crate::device_id::IdArray::new($table_data);\n-\n- $crate::module_device_table!(\"pci\", $module_table_name, $table_name);\n+ ($($tt:tt)*) =\u003e {\n+ $crate::module_device_table!(\"pci\", $crate::pci::DeviceId, $($tt)*);\n };\n }\n \n@@ -267,7 +261,6 @@ macro_rules! pci_device_table {\n ///\n /// kernel::pci_device_table!(\n /// PCI_TABLE,\n-/// MODULE_PCI_TABLE,\n /// \u003cMyDriver as pci::Driver\u003e::IdInfo,\n /// [\n /// (\n@@ -284,7 +277,7 @@ macro_rules! pci_device_table {\n ///\n /// fn probe\u003c'bound\u003e(\n /// _pdev: \u0026'bound pci::Device\u003cCore\u003c'_\u003e\u003e,\n-/// _id_info: \u0026'bound Self::IdInfo,\n+/// _id_info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n /// ) -\u003e impl PinInit\u003cSelf::Data\u003c'bound\u003e, Error\u003e + 'bound {\n /// Err(ENODEV)\n /// }\n@@ -313,7 +306,7 @@ pub trait Driver {\n /// attempt to initialize the device here.\n fn probe\u003c'bound\u003e(\n dev: \u0026'bound Device\u003cdevice::Core\u003c'_\u003e\u003e,\n- id_info: \u0026'bound Self::IdInfo,\n+ id_info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n ) -\u003e impl PinInit\u003cSelf::Data\u003c'bound\u003e, Error\u003e + 'bound;\n \n /// PCI driver unbind.\ndiff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs\nindex 9b362e0495d323..e12e88113ca5d2 100644\n--- a/rust/kernel/platform.rs\n+++ b/rust/kernel/platform.rs\n@@ -100,7 +100,8 @@ extern \"C\" fn probe_callback(pdev: *mut bindings::platform_device) -\u003e kernel::ff\n //\n // INVARIANT: `pdev` is valid for the duration of `probe_callback()`.\n let pdev = unsafe { \u0026*pdev.cast::\u003cDevice\u003cdevice::CoreInternal\u003c'_\u003e\u003e\u003e() };\n- let info = \u003cSelf as driver::Adapter\u003e::id_info(pdev.as_ref());\n+ // SAFETY: `pdev` matched data is of type `Self::IdInfo`.\n+ let info = unsafe { \u003cSelf as driver::Adapter\u003e::id_info(pdev.as_ref()) };\n \n from_result(|| {\n let data = T::probe(pdev, info);\n@@ -176,7 +177,6 @@ macro_rules! module_platform_driver {\n ///\n /// kernel::of_device_table!(\n /// OF_TABLE,\n-/// MODULE_OF_TABLE,\n /// \u003cMyDriver as platform::Driver\u003e::IdInfo,\n /// [\n /// (of::DeviceId::new(c\"test,device\"), ())\n@@ -185,7 +185,6 @@ macro_rules! module_platform_driver {\n ///\n /// kernel::acpi_device_table!(\n /// ACPI_TABLE,\n-/// MODULE_ACPI_TABLE,\n /// \u003cMyDriver as platform::Driver\u003e::IdInfo,\n /// [\n /// (acpi::DeviceId::new(c\"LNUXBEEF\"), ())\ndiff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs\nindex 7aff0c82d0afc0..aec7dce0495532 100644\n--- a/rust/kernel/usb.rs\n+++ b/rust/kernel/usb.rs\n@@ -89,7 +89,10 @@ extern \"C\" fn probe_callback(\n // does not add additional invariants, so it's safe to transmute.\n let id = unsafe { \u0026*id.cast::\u003cDeviceId\u003e() };\n \n- let info = T::ID_TABLE.info(id.index());\n+ // SAFETY: `id` comes from `T::ID_TABLE` which is of type `IdArray\u003c_, T::IdInfo\u003e`. It\n+ // can also come from dynamic IDs, which will ensure that `driver_data` exists in\n+ // `T::ID_TABLE` or is 0.\n+ let info = unsafe { id.info_unchecked_opt::\u003cT::IdInfo\u003e() };\n let data = T::probe(intf, id, info);\n \n let dev: \u0026device::Device\u003cdevice::CoreInternal\u003c'_\u003e\u003e = intf.as_ref();\n@@ -242,10 +245,6 @@ unsafe impl RawDeviceId for DeviceId {\n // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_info` field.\n unsafe impl RawDeviceIdIndex for DeviceId {\n const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::usb_device_id, driver_info);\n-\n- fn index(\u0026self) -\u003e usize {\n- self.0.driver_info\n- }\n }\n \n /// [`IdTable`](kernel::device_id::IdTable) type for USB.\n@@ -254,14 +253,8 @@ fn index(\u0026self) -\u003e usize {\n /// Create a USB `IdTable` with its alias for modpost.\n #[macro_export]\n macro_rules! usb_device_table {\n- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) =\u003e {\n- const $table_name: $crate::device_id::IdArray\u003c\n- $crate::usb::DeviceId,\n- $id_info_type,\n- { $table_data.len() },\n- \u003e = $crate::device_id::IdArray::new($table_data);\n-\n- $crate::module_device_table!(\"usb\", $module_table_name, $table_name);\n+ ($($tt:tt)*) =\u003e {\n+ $crate::module_device_table!(\"usb\", $crate::usb::DeviceId, $($tt)*);\n };\n }\n \n@@ -277,7 +270,6 @@ macro_rules! usb_device_table {\n ///\n /// kernel::usb_device_table!(\n /// USB_TABLE,\n-/// MODULE_USB_TABLE,\n /// \u003cMyDriver as usb::Driver\u003e::IdInfo,\n /// [\n /// (usb::DeviceId::from_id(0x1234, 0x5678), ()),\n@@ -293,7 +285,7 @@ macro_rules! usb_device_table {\n /// fn probe\u003c'bound\u003e(\n /// _interface: \u0026'bound usb::Interface\u003cCore\u003c'_\u003e\u003e,\n /// _id: \u0026usb::DeviceId,\n-/// _info: \u0026'bound Self::IdInfo,\n+/// _info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n /// ) -\u003e impl PinInit\u003cSelf::Data\u003c'bound\u003e, Error\u003e + 'bound {\n /// Err(ENODEV)\n /// }\n@@ -322,7 +314,7 @@ pub trait Driver {\n fn probe\u003c'bound\u003e(\n interface: \u0026'bound Interface\u003cdevice::Core\u003c'_\u003e\u003e,\n id: \u0026DeviceId,\n- id_info: \u0026'bound Self::IdInfo,\n+ id_info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n ) -\u003e impl PinInit\u003cSelf::Data\u003c'bound\u003e, Error\u003e + 'bound;\n \n /// USB driver disconnect.\ndiff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs\nindex 1f59e08aaa4b0d..181fd98ae5b663 100644\n--- a/samples/rust/rust_debugfs.rs\n+++ b/samples/rust/rust_debugfs.rs\n@@ -110,7 +110,6 @@ fn from_str(s: \u0026str) -\u003e Result\u003cSelf\u003e {\n \n kernel::acpi_device_table!(\n ACPI_TABLE,\n- MODULE_ACPI_TABLE,\n \u003cRustDebugFs as platform::Driver\u003e::IdInfo,\n [(acpi::DeviceId::new(c\"LNUXBEEF\"), ())]\n );\ndiff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs\nindex 5046b4628d0e29..80c309ce07e93e 100644\n--- a/samples/rust/rust_dma.rs\n+++ b/samples/rust/rust_dma.rs\n@@ -51,7 +51,6 @@ unsafe impl kernel::transmute::FromBytes for MyStruct {}\n \n kernel::pci_device_table!(\n PCI_TABLE,\n- MODULE_PCI_TABLE,\n \u003cDmaSampleDriver as pci::Driver\u003e::IdInfo,\n [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]\n );\n@@ -63,7 +62,7 @@ impl pci::Driver for DmaSampleDriver {\n \n fn probe\u003c'bound\u003e(\n pdev: \u0026'bound pci::Device\u003cCore\u003c'_\u003e\u003e,\n- _info: \u0026'bound Self::IdInfo,\n+ _info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n ) -\u003e impl PinInit\u003cSelf, Error\u003e + 'bound {\n pin_init::pin_init_scope(move || {\n dev_info!(pdev, \"Probe DMA test driver.\\n\");\ndiff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driver_auxiliary.rs\nindex 2c1351040e45e5..704567a072bac3 100644\n--- a/samples/rust/rust_driver_auxiliary.rs\n+++ b/samples/rust/rust_driver_auxiliary.rs\n@@ -24,7 +24,6 @@\n \n kernel::auxiliary_device_table!(\n AUX_TABLE,\n- MODULE_AUX_TABLE,\n \u003cAuxiliaryDriver as auxiliary::Driver\u003e::IdInfo,\n [(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]\n );\n@@ -66,7 +65,6 @@ struct ParentData\u003c'bound\u003e {\n \n kernel::pci_device_table!(\n PCI_TABLE,\n- MODULE_PCI_TABLE,\n \u003cParentDriver as pci::Driver\u003e::IdInfo,\n [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]\n );\n@@ -79,7 +77,7 @@ impl pci::Driver for ParentDriver {\n \n fn probe\u003c'bound\u003e(\n pdev: \u0026'bound pci::Device\u003cCore\u003c'_\u003e\u003e,\n- _info: \u0026'bound Self::IdInfo,\n+ _info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n ) -\u003e impl PinInit\u003cSelf::Data\u003c'bound\u003e, Error\u003e + 'bound {\n Ok(ParentData {\n // SAFETY: `ParentData` is the driver's private data, which is dropped when the\ndiff --git a/samples/rust/rust_driver_i2c.rs b/samples/rust/rust_driver_i2c.rs\nindex ead8263a7d489a..a0df0c6097c4f5 100644\n--- a/samples/rust/rust_driver_i2c.rs\n+++ b/samples/rust/rust_driver_i2c.rs\n@@ -14,21 +14,18 @@\n \n kernel::acpi_device_table! {\n ACPI_TABLE,\n- MODULE_ACPI_TABLE,\n \u003cSampleDriver as i2c::Driver\u003e::IdInfo,\n [(acpi::DeviceId::new(c\"LNUXBEEF\"), 0)]\n }\n \n kernel::i2c_device_table! {\n I2C_TABLE,\n- MODULE_I2C_TABLE,\n \u003cSampleDriver as i2c::Driver\u003e::IdInfo,\n [(i2c::DeviceId::new(c\"rust_driver_i2c\"), 0)]\n }\n \n kernel::of_device_table! {\n OF_TABLE,\n- MODULE_OF_TABLE,\n \u003cSampleDriver as i2c::Driver\u003e::IdInfo,\n [(of::DeviceId::new(c\"test,rust_driver_i2c\"), 0)]\n }\ndiff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci.rs\nindex 1aa8197d8698c0..652819dff0824b 100644\n--- a/samples/rust/rust_driver_pci.rs\n+++ b/samples/rust/rust_driver_pci.rs\n@@ -74,12 +74,10 @@ struct SampleDriverData\u003c'bound\u003e {\n \n kernel::pci_device_table!(\n PCI_TABLE,\n- MODULE_PCI_TABLE,\n \u003cSampleDriver as pci::Driver\u003e::IdInfo,\n- [(\n- pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5),\n- TestIndex::NO_EVENTFD\n- )]\n+ {\n+ pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5) =\u003e TestIndex::NO_EVENTFD,\n+ }\n );\n \n impl SampleDriverData\u003c'_\u003e {\n@@ -144,7 +142,7 @@ impl pci::Driver for SampleDriver {\n \n fn probe\u003c'bound\u003e(\n pdev: \u0026'bound pci::Device\u003cCore\u003c'_\u003e\u003e,\n- info: \u0026'bound Self::IdInfo,\n+ info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n ) -\u003e impl PinInit\u003cSelf::Data\u003c'bound\u003e, Error\u003e + 'bound {\n let vendor = pdev.vendor_id();\n dev_dbg!(\n@@ -153,6 +151,7 @@ fn probe\u003c'bound\u003e(\n vendor,\n pdev.device_id()\n );\n+ let info = info.ok_or(ENODEV)?;\n \n pdev.enable_device_mem()?;\n pdev.set_master();\ndiff --git a/samples/rust/rust_driver_platform.rs b/samples/rust/rust_driver_platform.rs\nindex ec0d6cac4f570b..710145b3605a21 100644\n--- a/samples/rust/rust_driver_platform.rs\n+++ b/samples/rust/rust_driver_platform.rs\n@@ -87,14 +87,12 @@ struct SampleDriver {\n \n kernel::of_device_table!(\n OF_TABLE,\n- MODULE_OF_TABLE,\n \u003cSampleDriver as platform::Driver\u003e::IdInfo,\n [(of::DeviceId::new(c\"test,rust-device\"), Info(42))]\n );\n \n kernel::acpi_device_table!(\n ACPI_TABLE,\n- MODULE_ACPI_TABLE,\n \u003cSampleDriver as platform::Driver\u003e::IdInfo,\n [(acpi::DeviceId::new(c\"LNUXBEEF\"), Info(0))]\n );\ndiff --git a/samples/rust/rust_driver_usb.rs b/samples/rust/rust_driver_usb.rs\nindex 02bd5085f9bc76..7ef04e177c8094 100644\n--- a/samples/rust/rust_driver_usb.rs\n+++ b/samples/rust/rust_driver_usb.rs\n@@ -19,7 +19,6 @@ struct SampleDriver {\n \n kernel::usb_device_table!(\n USB_TABLE,\n- MODULE_USB_TABLE,\n \u003cSampleDriver as usb::Driver\u003e::IdInfo,\n [(usb::DeviceId::from_id(0x1234, 0x5678), ()),]\n );\n@@ -32,7 +31,7 @@ impl usb::Driver for SampleDriver {\n fn probe\u003c'bound\u003e(\n intf: \u0026'bound usb::Interface\u003cCore\u003c'_\u003e\u003e,\n _id: \u0026usb::DeviceId,\n- _info: \u0026'bound Self::IdInfo,\n+ _info: Option\u003c\u0026'bound Self::IdInfo\u003e,\n ) -\u003e impl PinInit\u003cSelf, Error\u003e + 'bound {\n let dev: \u0026device::Device\u003cCore\u003c'_\u003e\u003e = intf.as_ref();\n dev_info!(dev, \"Rust USB driver sample probed\\n\");\ndiff --git a/samples/rust/rust_i2c_client.rs b/samples/rust/rust_i2c_client.rs\nindex 2d876f4e3ee0a2..c8a23875ef5bc5 100644\n--- a/samples/rust/rust_i2c_client.rs\n+++ b/samples/rust/rust_i2c_client.rs\n@@ -87,14 +87,12 @@ struct SampleDriver {\n \n kernel::of_device_table!(\n OF_TABLE,\n- MODULE_OF_TABLE,\n \u003cSampleDriver as platform::Driver\u003e::IdInfo,\n [(of::DeviceId::new(c\"test,rust-device\"), ())]\n );\n \n kernel::acpi_device_table!(\n ACPI_TABLE,\n- MODULE_ACPI_TABLE,\n \u003cSampleDriver as platform::Driver\u003e::IdInfo,\n [(acpi::DeviceId::new(c\"LNUXBEEF\"), ())]\n );\ndiff --git a/samples/rust/rust_soc.rs b/samples/rust/rust_soc.rs\nindex 808d58200eb677..f5e5f2f9adf762 100644\n--- a/samples/rust/rust_soc.rs\n+++ b/samples/rust/rust_soc.rs\n@@ -23,14 +23,12 @@ struct SampleSocDriver {\n \n kernel::of_device_table!(\n OF_TABLE,\n- MODULE_OF_TABLE,\n \u003cSampleSocDriver as platform::Driver\u003e::IdInfo,\n [(of::DeviceId::new(c\"test,rust-device\"), ())]\n );\n \n kernel::acpi_device_table!(\n ACPI_TABLE,\n- MODULE_ACPI_TABLE,\n \u003cSampleSocDriver as platform::Driver\u003e::IdInfo,\n [(acpi::DeviceId::new(c\"LNUXBEEF\"), ())]\n );\n"
} |
| 2/1 | 2026/06/29 13:13 | agent | patch-evaluator |
3mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"RUST",
"SAMPLES_RUST",
"SAMPLE_RUST_DMA",
"SAMPLE_RUST_DRIVER_I2C",
"SAMPLE_RUST_I2C_CLIENT",
"SAMPLE_RUST_DRIVER_PCI",
"SAMPLE_RUST_DRIVER_PLATFORM",
"SAMPLE_RUST_DRIVER_USB",
"SAMPLE_RUST_DRIVER_AUXILIARY",
"SAMPLE_RUST_SOC",
"DRM_NOVA",
"DRM_TYR",
"NOVA_CORE",
"PWM_TH1520",
"CPUFREQ_DT_RUST",
"AX88796B_RUST_PHY",
"AMCC_QT2025_PHY"
],
"FocusSymbols": [],
"Reasoning": "The patch modifies core Rust abstractions for device drivers (PCI, USB, Platform, I2C, Auxiliary, ACPI, OF), changing how device ID tables are generated and how match data is retrieved during driver probe. Fuzzing is needed to ensure Rust drivers can still probe successfully and receive correct match data.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 1f3cc9a5a864751ea4393bef6c3e8486f48b1a6b
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Jun 29 13:13:08 2026 +0000
syz-cluster: applied patch under review
diff --git a/MAINTAINERS b/MAINTAINERS
index 15011f5752a994..07240e0b745180 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -297,7 +297,6 @@ F: include/linux/acpi.h
F: include/linux/fwnode.h
F: include/linux/fw_table.h
F: lib/fw_table.c
-F: rust/helpers/acpi.c
F: rust/kernel/acpi.rs
F: tools/power/acpi/
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index a30a904f6535f4..1fb0b10bf92479 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -898,9 +898,9 @@ const struct acpi_device *acpi_companion_match(const struct device *dev)
* identifiers and a _DSD object with the "compatible" property, use that
* property to match against the given list of identifiers.
*/
-bool acpi_of_match_device(const struct acpi_device *adev,
- const struct of_device_id *of_match_table,
- const struct of_device_id **of_id)
+static bool acpi_of_match_device(const struct acpi_device *adev,
+ const struct of_device_id *of_match_table,
+ const struct of_device_id **of_id)
{
const union acpi_object *of_compatible, *obj;
int i, nval;
diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs
index 10106fa13095e4..145daa12072f49 100644
--- a/drivers/cpufreq/rcpufreq_dt.rs
+++ b/drivers/cpufreq/rcpufreq_dt.rs
@@ -194,7 +194,6 @@ fn register_em(policy: &mut cpufreq::Policy) {
kernel::of_device_table!(
OF_TABLE,
- MODULE_OF_TABLE,
<CPUFreqDTDriver as platform::Driver>::IdInfo,
[(of::DeviceId::new(c"operating-points-v2"), ())]
);
diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs
index 48933d86ddda9b..43f15cdfeb09b3 100644
--- a/drivers/gpu/drm/nova/driver.rs
+++ b/drivers/gpu/drm/nova/driver.rs
@@ -43,7 +43,6 @@ pub(crate) struct NovaData {
kernel::auxiliary_device_table!(
AUX_TABLE,
- MODULE_AUX_TABLE,
<NovaDriver as auxiliary::Driver>::IdInfo,
[(
auxiliary::DeviceId::new(NOVA_CORE_MODULE_NAME, AUXILIARY_NAME),
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index d063bc664cc117..218e9af899c7c7 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -87,7 +87,6 @@ fn issue_soft_reset(dev: &Device, iomem: &IoMem<'_>) -> Result {
kernel::of_device_table!(
OF_TABLE,
- MODULE_OF_TABLE,
<TyrPlatformDriver as platform::Driver>::IdInfo,
[
(of::DeviceId::new(c"rockchip,rk3588-mali"), ()),
diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs
index 5738d4ac521b72..0c53b7239ac9e9 100644
--- a/drivers/gpu/nova-core/driver.rs
+++ b/drivers/gpu/nova-core/driver.rs
@@ -40,7 +40,6 @@ pub(crate) struct NovaCore<'bound> {
kernel::pci_device_table!(
PCI_TABLE,
- MODULE_PCI_TABLE,
<NovaCoreDriver as pci::Driver>::IdInfo,
[
// Modern NVIDIA GPUs will show up as either VGA or 3D controllers.
@@ -70,7 +69,7 @@ impl pci::Driver for NovaCoreDriver {
fn probe<'bound>(
pdev: &'bound pci::Device<Core<'_>>,
- _info: &'bound Self::IdInfo,
+ _info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
pin_init::pin_init_scope(move || {
dev_dbg!(pdev, "Probe Nova Core GPU driver.\n");
diff --git a/drivers/pwm/pwm_th1520.rs b/drivers/pwm/pwm_th1520.rs
index 3e3fa51ccef911..1df752330e8fd9 100644
--- a/drivers/pwm/pwm_th1520.rs
+++ b/drivers/pwm/pwm_th1520.rs
@@ -303,7 +303,6 @@ fn drop(self: Pin<&mut Self>) {
kernel::of_device_table!(
OF_TABLE,
- MODULE_OF_TABLE,
<Th1520PwmPlatformDriver as platform::Driver>::IdInfo,
[(of::DeviceId::new(c"thead,th1520-pwm"), ())]
);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 714d111d80530f..7e57f9698f7ced 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -189,10 +189,6 @@ struct acpi_driver {
* -----------
*/
-bool acpi_of_match_device(const struct acpi_device *adev,
- const struct of_device_id *of_match_table,
- const struct of_device_id **of_id);
-
/* Status (_STA) */
struct acpi_device_status {
@@ -1000,13 +996,6 @@ int acpi_scan_add_dep(acpi_handle handle, struct acpi_handle_list *dep_devices);
u32 arch_acpi_add_auto_dep(acpi_handle handle);
#else /* CONFIG_ACPI */
-static inline bool acpi_of_match_device(const struct acpi_device *adev,
- const struct of_device_id *of_match_table,
- const struct of_device_id **of_id)
-{
- return false;
-}
-
static inline int register_acpi_bus_type(void *bus) { return 0; }
static inline int unregister_acpi_bus_type(void *bus) { return 0; }
diff --git a/rust/helpers/acpi.c b/rust/helpers/acpi.c
deleted file mode 100644
index e75c9807bbadcc..00000000000000
--- a/rust/helpers/acpi.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-
-__rust_helper bool rust_helper_acpi_of_match_device(const struct acpi_device *adev,
- const struct of_device_id *of_match_table,
- const struct of_device_id **of_id)
-{
- return acpi_of_match_device(adev, of_match_table, of_id);
-}
-
-__rust_helper struct acpi_device *rust_helper_to_acpi_device_node(struct fwnode_handle *fwnode)
-{
- return to_acpi_device_node(fwnode);
-}
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 998e31052e6601..fadd7acdd81c93 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -38,7 +38,6 @@
#define __rust_helper __always_inline
#endif
-#include "acpi.c"
#include "atomic.c"
#include "atomic_ext.c"
#include "auxiliary.c"
diff --git a/rust/kernel/acpi.rs b/rust/kernel/acpi.rs
index 9b8efa623130c1..ea2ce61ee3931f 100644
--- a/rust/kernel/acpi.rs
+++ b/rust/kernel/acpi.rs
@@ -25,10 +25,6 @@ unsafe impl RawDeviceId for DeviceId {
// SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.
unsafe impl RawDeviceIdIndex for DeviceId {
const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::acpi_device_id, driver_data);
-
- fn index(&self) -> usize {
- self.0.driver_data
- }
}
impl DeviceId {
@@ -53,13 +49,7 @@ pub const fn new(id: &'static CStr) -> Self {
/// Create an ACPI `IdTable` with an "alias" for modpost.
#[macro_export]
macro_rules! acpi_device_table {
- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => {
- const $table_name: $crate::device_id::IdArray<
- $crate::acpi::DeviceId,
- $id_info_type,
- { $table_data.len() },
- > = $crate::device_id::IdArray::new($table_data);
-
- $crate::module_device_table!("acpi", $module_table_name, $table_name);
+ ($($tt:tt)*) => {
+ $crate::module_device_table!("acpi", $crate::acpi::DeviceId, $($tt)*);
};
}
diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index c42928d5a2393f..aa13d8866a1964 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -93,7 +93,9 @@ extern "C" fn probe_callback(
// SAFETY: `DeviceId` is a `#[repr(transparent)`] wrapper of `struct auxiliary_device_id`
// and does not add additional invariants, so it's safe to transmute.
let id = unsafe { &*id.cast::<DeviceId>() };
- let info = T::ID_TABLE.info(id.index());
+
+ // SAFETY: `id` comes from `T::ID_TABLE` which is of type `IdArray<_, T::IdInfo>`.
+ let info = unsafe { id.info_unchecked::<T::IdInfo>() };
from_result(|| {
let data = T::probe(adev, info);
@@ -169,10 +171,6 @@ unsafe impl RawDeviceId for DeviceId {
unsafe impl RawDeviceIdIndex for DeviceId {
const DRIVER_DATA_OFFSET: usize =
core::mem::offset_of!(bindings::auxiliary_device_id, driver_data);
-
- fn index(&self) -> usize {
- self.0.driver_data
- }
}
/// IdTable type for auxiliary drivers.
@@ -181,14 +179,8 @@ fn index(&self) -> usize {
/// Create a auxiliary `IdTable` with its alias for modpost.
#[macro_export]
macro_rules! auxiliary_device_table {
- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => {
- const $table_name: $crate::device_id::IdArray<
- $crate::auxiliary::DeviceId,
- $id_info_type,
- { $table_data.len() },
- > = $crate::device_id::IdArray::new($table_data);
-
- $crate::module_device_table!("auxiliary", $module_table_name, $table_name);
+ ($($tt:tt)*) => {
+ $crate::module_device_table!("auxiliary", $crate::auxiliary::DeviceId, $($tt)*);
};
}
diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
index 8e97214460146e..5f4d191fce515a 100644
--- a/rust/kernel/device_id.rs
+++ b/rust/kernel/device_id.rs
@@ -5,7 +5,10 @@
//! Each bus / subsystem that matches device and driver through a bus / subsystem specific ID is
//! expected to implement [`RawDeviceId`].
-use core::mem::MaybeUninit;
+use core::{
+ marker::PhantomData,
+ mem::MaybeUninit, //
+};
/// Marker trait to indicate a Rust device ID type represents a corresponding C device ID type.
///
@@ -47,112 +50,110 @@ pub unsafe trait RawDeviceIdIndex: RawDeviceId {
/// The offset (in bytes) to the context/data field in the raw device ID.
const DRIVER_DATA_OFFSET: usize;
- /// The index stored at `DRIVER_DATA_OFFSET` of the implementor of the [`RawDeviceIdIndex`]
- /// trait.
- fn index(&self) -> usize;
-}
-
-/// A zero-terminated device id array.
-#[repr(C)]
-pub struct RawIdArray<T: RawDeviceId, const N: usize> {
- ids: [T::RawType; N],
- sentinel: MaybeUninit<T::RawType>,
-}
+ /// Obtain the data pointer stored inside the device ID.
+ ///
+ /// # Safety
+ ///
+ /// `&Self` must be stored inside a `IdArray<Self, U>`.
+ unsafe fn info_unchecked<U>(&self) -> &'static U {
+ // SAFETY: By safety requirement of the trait, this is `self.driver_data as *const U` and by
+ // the safety requirement of the function, this is stored in `IdArray<Self, U>` so is
+ // convertible to `&'static U`.
+ unsafe {
+ core::ptr::from_ref(self)
+ .byte_add(Self::DRIVER_DATA_OFFSET)
+ .cast::<&U>()
+ .read()
+ }
+ }
-impl<T: RawDeviceId, const N: usize> RawIdArray<T, N> {
- #[doc(hidden)]
- pub const fn size(&self) -> usize {
- core::mem::size_of::<Self>()
+ /// Obtain the data pointer stored inside the device ID.
+ ///
+ /// # Safety
+ ///
+ /// `&Self` must be stored inside a `IdArray<Self, U>`, or has NULL (or 0) as driver data.
+ unsafe fn info_unchecked_opt<U>(&self) -> Option<&'static U> {
+ // SAFETY: By safety requirement of the trait, this is `self.driver_data as *const U` and by
+ // the safety requirement of the function, if this is stored in `IdArray<Self, U>`, this is
+ // convertible to `Option<&'static U>`. Otherwise it is NULL which is `None` as
+ // `Option<&U>`.
+ unsafe {
+ core::ptr::from_ref(self)
+ .byte_add(Self::DRIVER_DATA_OFFSET)
+ .cast::<Option<&U>>()
+ .read()
+ }
}
}
/// A zero-terminated device id array, followed by context data.
#[repr(C)]
-pub struct IdArray<T: RawDeviceId, U, const N: usize> {
- raw_ids: RawIdArray<T, N>,
- id_infos: [U; N],
+pub struct IdArray<T: RawDeviceId, U: 'static, const N: usize> {
+ // This is `MaybeUninit<T::RawType>` so any bytes inside it can carry provenance in CTFE.
+ // If this were `T::RawType`, integer fields would not be able to contain pointers.
+ ids: [MaybeUninit<T::RawType>; N],
+ sentinel: MaybeUninit<T::RawType>,
+ phantom: PhantomData<&'static U>,
}
-impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
+// SAFETY: device ID is plain data plus a `&'static U` and can thus be sent between threads safely
+// if `&U` can.
+unsafe impl<T: RawDeviceId, U: Sync + 'static, const N: usize> Send for IdArray<T, U, N> {}
+
+// SAFETY: device ID is plain data plus a `&'static U` and can thus be shared between threads safely
+// if `&U` can.
+unsafe impl<T: RawDeviceId, U: Sync + 'static, const N: usize> Sync for IdArray<T, U, N> {}
+
+impl<T: RawDeviceId + RawDeviceIdIndex, U: 'static, const N: usize> IdArray<T, U, N> {
/// Creates a new instance of the array.
///
/// The contents are derived from the given identifiers and context information.
- ///
- /// # Safety
- ///
- /// `data_offset` as `None` is always safe.
- /// If `data_offset` is `Some(data_offset)`, then:
- /// - `data_offset` must be the correct offset (in bytes) to the context/data field
- /// (e.g., the `driver_data` field) within the raw device ID structure.
- /// - The field at `data_offset` must be correctly sized to hold a `usize`.
- const unsafe fn build(ids: [(T, U); N], data_offset: Option<usize>) -> Self {
+ pub const fn new(ids: [(T, &'static U); N]) -> Self {
let mut raw_ids = [const { MaybeUninit::<T::RawType>::uninit() }; N];
- let mut infos = [const { MaybeUninit::uninit() }; N];
let mut i = 0usize;
while i < N {
// SAFETY: by the safety requirement of `RawDeviceId`, we're guaranteed that `T` is
// layout-wise compatible with `RawType`.
raw_ids[i] = unsafe { core::mem::transmute_copy(&ids[i].0) };
- if let Some(data_offset) = data_offset {
- // SAFETY: by the safety requirement of this function, this would be effectively
- // `raw_ids[i].driver_data = i;`.
- unsafe {
- raw_ids[i]
- .as_mut_ptr()
- .byte_add(data_offset)
- .cast::<usize>()
- .write(i);
- }
+ // SAFETY: by the safety requirement of `RawDeviceIdIndex`, this would be effectively
+ // `raw_ids[i].driver_data = ids[i].1;`.
+ unsafe {
+ raw_ids[i]
+ .as_mut_ptr()
+ .byte_add(T::DRIVER_DATA_OFFSET)
+ .cast::<&U>()
+ .write(ids[i].1);
}
- // SAFETY: this is effectively a move: `infos[i] = ids[i].1`. We make a copy here but
- // later forget `ids`.
- infos[i] = MaybeUninit::new(unsafe { core::ptr::read(&ids[i].1) });
i += 1;
}
core::mem::forget(ids);
Self {
- raw_ids: RawIdArray {
- // SAFETY: this is effectively `array_assume_init`, which is unstable, so we use
- // `transmute_copy` instead. We have initialized all elements of `raw_ids` so this
- // `array_assume_init` is safe.
- ids: unsafe { core::mem::transmute_copy(&raw_ids) },
- sentinel: MaybeUninit::zeroed(),
- },
- // SAFETY: We have initialized all elements of `infos` so this `array_assume_init` is
- // safe.
- id_infos: unsafe { core::mem::transmute_copy(&infos) },
+ ids: raw_ids,
+ sentinel: MaybeUninit::zeroed(),
+ phantom: PhantomData,
}
}
+}
+impl<T: RawDeviceId, const N: usize> IdArray<T, (), N> {
/// Creates a new instance of the array without writing index values.
///
/// The contents are derived from the given identifiers and context information.
/// If the device implements [`RawDeviceIdIndex`], consider using [`IdArray::new`] instead.
- pub const fn new_without_index(ids: [(T, U); N]) -> Self {
- // SAFETY: Calling `Self::build` with `offset = None` is always safe,
- // because no raw memory writes are performed in this case.
- unsafe { Self::build(ids, None) }
- }
-
- /// Reference to the contained [`RawIdArray`].
- pub const fn raw_ids(&self) -> &RawIdArray<T, N> {
- &self.raw_ids
- }
-}
+ pub const fn new_without_index(ids: [T; N]) -> Self {
+ // SAFETY: `T` is layout-wise compatible with `T::RawType`, so is the array of them.
+ let raw_ids: [MaybeUninit<T::RawType>; N] = unsafe { core::mem::transmute_copy(&ids) };
+ core::mem::forget(ids);
-impl<T: RawDeviceId + RawDeviceIdIndex, U, const N: usize> IdArray<T, U, N> {
- /// Creates a new instance of the array.
- ///
- /// The contents are derived from the given identifiers and context information.
- pub const fn new(ids: [(T, U); N]) -> Self {
- // SAFETY: by the safety requirement of `RawDeviceIdIndex`,
- // `T::DRIVER_DATA_OFFSET` is guaranteed to be the correct offset (in bytes) to
- // a field within `T::RawType`.
- unsafe { Self::build(ids, Some(T::DRIVER_DATA_OFFSET)) }
+ Self {
+ ids: raw_ids,
+ sentinel: MaybeUninit::zeroed(),
+ phantom: PhantomData,
+ }
}
}
@@ -165,12 +166,6 @@ impl<T: RawDeviceId + RawDeviceIdIndex, U, const N: usize> IdArray<T, U, N> {
pub trait IdTable<T: RawDeviceId, U> {
/// Obtain the pointer to the ID table.
fn as_ptr(&self) -> *const T::RawType;
-
- /// Obtain the pointer to the bus specific device ID from an index.
- fn id(&self, index: usize) -> &T::RawType;
-
- /// Obtain the pointer to the driver-specific information from an index.
- fn info(&self, index: usize) -> &U;
}
impl<T: RawDeviceId, U, const N: usize> IdTable<T, U> for IdArray<T, U, N> {
@@ -179,28 +174,56 @@ fn as_ptr(&self) -> *const T::RawType {
// to access the sentinel.
core::ptr::from_ref(self).cast()
}
-
- fn id(&self, index: usize) -> &T::RawType {
- &self.raw_ids.ids[index]
- }
-
- fn info(&self, index: usize) -> &U {
- &self.id_infos[index]
- }
}
/// Create device table alias for modpost.
#[macro_export]
macro_rules! module_device_table {
- ($table_type: literal, $module_table_name:ident, $table_name:ident) => {
- #[rustfmt::skip]
+ (
+ $table_type: literal, $device_id_ty: ty,
+ $table_name: ident, $id_info_type: ty,
+ [$(($id: expr, $info:expr $(,)?)),* $(,)?]
+ ) => {
+ $crate::module_device_table!(
+ $table_type, $device_id_ty, $table_name, $id_info_type,
+ {$($id=>$info,)*}
+ );
+ };
+
+ (
+ $table_type: literal, $device_id_ty: ty,
+ $table_name: ident, $id_info_type: ty,
+ {$($id: expr => $info:expr),* $(,)?}
+ ) => {
+ #[export_name =
+ concat!("__mod_device_table__", ::core::line!(),
+ "__kmod_", module_path!(),
+ "__", $table_type,
+ "__", stringify!($table_name))
+ ]
+ static $table_name: $crate::device_id::IdArray<
+ $device_id_ty,
+ $id_info_type,
+ { <[$device_id_ty]>::len(&[$($id,)*]) },
+ > = $crate::device_id::IdArray::new([$(($id, &$info),)*]);
+ };
+
+ // Case for no ID info.
+ (
+ $table_type: literal, $device_id_ty: ty,
+ $table_name: ident, @none,
+ [$($id: expr),* $(,)?]
+ ) => {
#[export_name =
- concat!("__mod_device_table__", line!(),
+ concat!("__mod_device_table__", ::core::line!(),
"__kmod_", module_path!(),
"__", $table_type,
"__", stringify!($table_name))
]
- static $module_table_name: [::core::mem::MaybeUninit<u8>; $table_name.raw_ids().size()] =
- unsafe { ::core::mem::transmute_copy($table_name.raw_ids()) };
+ static $table_name: $crate::device_id::IdArray<
+ $device_id_ty,
+ (),
+ { <[$device_id_ty]>::len(&[$($id,)*]) },
+ > = $crate::device_id::IdArray::new_without_index([$($id),*]);
};
}
diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
index bf5ba0d27553ed..c9c74c4dde8fa7 100644
--- a/rust/kernel/driver.rs
+++ b/rust/kernel/driver.rs
@@ -291,26 +291,6 @@ fn init(
}
}
-// Calling the FFI function directly from the `Adapter` impl may result in it being called
-// directly from driver modules. This happens since the Rust compiler will use monomorphisation, so
-// it might happen that functions are instantiated within the calling driver module. For now, work
-// around this with `#[inline(never)]` helpers.
-//
-// TODO: Remove once a more generic solution has been implemented. For instance, we may be able to
-// leverage `bindgen` to take care of this depending on whether a symbol is (already) exported.
-#[inline(never)]
-#[allow(clippy::missing_safety_doc)]
-#[allow(dead_code)]
-#[must_use]
-unsafe fn acpi_of_match_device(
- adev: *const bindings::acpi_device,
- of_match_table: *const bindings::of_device_id,
- of_id: *mut *const bindings::of_device_id,
-) -> bool {
- // SAFETY: Safety requirements are the same as `bindings::acpi_of_match_device`.
- unsafe { bindings::acpi_of_match_device(adev, of_match_table, of_id) }
-}
-
/// The bus independent adapter to match a drivers and a devices.
///
/// This trait should be implemented by the bus specific adapter, which represents the connection
@@ -324,118 +304,23 @@ pub trait Adapter {
/// The [`acpi::IdTable`] of the corresponding driver
fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>>;
- /// Returns the driver's private data from the matching entry in the [`acpi::IdTable`], if any.
- ///
- /// If this returns `None`, it means there is no match with an entry in the [`acpi::IdTable`].
- fn acpi_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
- #[cfg(not(CONFIG_ACPI))]
- {
- let _ = dev;
- None
- }
-
- #[cfg(CONFIG_ACPI)]
- {
- let table = Self::acpi_id_table()?;
-
- // SAFETY:
- // - `table` has static lifetime, hence it's valid for read,
- // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.
- let raw_id = unsafe { bindings::acpi_match_device(table.as_ptr(), dev.as_raw()) };
-
- if raw_id.is_null() {
- None
- } else {
- // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct acpi_device_id`
- // and does not add additional invariants, so it's safe to transmute.
- let id = unsafe { &*raw_id.cast::<acpi::DeviceId>() };
-
- Some(table.info(<acpi::DeviceId as crate::device_id::RawDeviceIdIndex>::index(id)))
- }
- }
- }
-
/// The [`of::IdTable`] of the corresponding driver.
fn of_id_table() -> Option<of::IdTable<Self::IdInfo>>;
- /// Returns the driver's private data from the matching entry in the [`of::IdTable`], if any.
- ///
- /// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`].
- fn of_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
- let table = Self::of_id_table()?;
-
- #[cfg(not(any(CONFIG_OF, CONFIG_ACPI)))]
- {
- let _ = (dev, table);
- }
-
- #[cfg(CONFIG_OF)]
- {
- // SAFETY:
- // - `table` has static lifetime, hence it's valid for read,
- // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.
- let raw_id = unsafe { bindings::of_match_device(table.as_ptr(), dev.as_raw()) };
-
- if !raw_id.is_null() {
- // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`
- // and does not add additional invariants, so it's safe to transmute.
- let id = unsafe { &*raw_id.cast::<of::DeviceId>() };
-
- return Some(table.info(
- <of::DeviceId as crate::device_id::RawDeviceIdIndex>::index(id),
- ));
- }
- }
-
- #[cfg(CONFIG_ACPI)]
- {
- use core::ptr;
- use device::property::FwNode;
-
- let mut raw_id = ptr::null();
-
- let fwnode = dev.fwnode().map_or(ptr::null_mut(), FwNode::as_raw);
-
- // SAFETY: `fwnode` is a pointer to a valid `fwnode_handle`. A null pointer will be
- // passed through the function.
- let adev = unsafe { bindings::to_acpi_device_node(fwnode) };
-
- // SAFETY:
- // - `adev` is a valid pointer to `acpi_device` or is null. It is guaranteed to be
- // valid as long as `dev` is alive.
- // - `table` has static lifetime, hence it's valid for read.
- if unsafe { acpi_of_match_device(adev, table.as_ptr(), &raw mut raw_id) } {
- // SAFETY:
- // - the function returns true, therefore `raw_id` has been set to a pointer to a
- // valid `of_device_id`.
- // - `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`
- // and does not add additional invariants, so it's safe to transmute.
- let id = unsafe { &*raw_id.cast::<of::DeviceId>() };
-
- return Some(table.info(
- <of::DeviceId as crate::device_id::RawDeviceIdIndex>::index(id),
- ));
- }
- }
-
- None
- }
-
/// Returns the driver's private data from the matching entry of any of the ID tables, if any.
///
/// If this returns `None`, it means that there is no match in any of the ID tables directly
/// associated with a [`device::Device`].
- fn id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
- let id = Self::acpi_id_info(dev);
- if id.is_some() {
- return id;
- }
-
- let id = Self::of_id_info(dev);
- if id.is_some() {
- return id;
- }
-
- None
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure that the `dev` matched data is of type `Self::IdInfo`.
+ #[inline]
+ unsafe fn id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
+ // SAFETY: `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.
+ let data = unsafe { bindings::device_get_match_data(dev.as_raw()) };
+
+ // SAFETY: Per safety requirement, `data` is of type `Self::IdInfo`.
+ unsafe { data.cast::<Self::IdInfo>().as_ref() }
}
}
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
index 624b971ca8b0b2..2d2191164e252c 100644
--- a/rust/kernel/i2c.rs
+++ b/rust/kernel/i2c.rs
@@ -65,10 +65,6 @@ unsafe impl RawDeviceId for DeviceId {
// SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.
unsafe impl RawDeviceIdIndex for DeviceId {
const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::i2c_device_id, driver_data);
-
- fn index(&self) -> usize {
- self.0.driver_data
- }
}
/// IdTable type for I2C
@@ -77,14 +73,8 @@ fn index(&self) -> usize {
/// Create a I2C `IdTable` with its alias for modpost.
#[macro_export]
macro_rules! i2c_device_table {
- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => {
- const $table_name: $crate::device_id::IdArray<
- $crate::i2c::DeviceId,
- $id_info_type,
- { $table_data.len() },
- > = $crate::device_id::IdArray::new($table_data);
-
- $crate::module_device_table!("i2c", $module_table_name, $table_name);
+ ($($tt:tt)*) => {
+ $crate::module_device_table!("i2c", $crate::i2c::DeviceId, $($tt)*);
};
}
@@ -159,8 +149,10 @@ extern "C" fn probe_callback(idev: *mut bindings::i2c_client) -> kernel::ffi::c_
// INVARIANT: `idev` is valid for the duration of `probe_callback()`.
let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal<'_>>>() };
- let info =
- Self::i2c_id_info(idev).or_else(|| <Self as driver::Adapter>::id_info(idev.as_ref()));
+ let info = Self::i2c_id_info(idev).or_else(|| {
+ // SAFETY: `idev` matched data is of type `Self::IdInfo`.
+ unsafe { <Self as driver::Adapter>::id_info(idev.as_ref()) }
+ });
from_result(|| {
let data = T::probe(idev, info);
@@ -218,7 +210,8 @@ fn i2c_id_info(dev: &I2cClient) -> Option<&'static <Self as driver::Adapter>::Id
// does not add additional invariants, so it's safe to transmute.
let id = unsafe { &*raw_id.cast::<DeviceId>() };
- Some(table.info(<DeviceId as RawDeviceIdIndex>::index(id)))
+ // SAFETY: `id` comes from `table` which is of type `IdArray<_, Self::IdInfo>`.
+ Some(unsafe { id.info_unchecked::<T::IdInfo>() })
}
}
@@ -267,7 +260,6 @@ macro_rules! module_i2c_driver {
///
/// kernel::acpi_device_table!(
/// ACPI_TABLE,
-/// MODULE_ACPI_TABLE,
/// <MyDriver as i2c::Driver>::IdInfo,
/// [
/// (acpi::DeviceId::new(c"LNUXBEEF"), ())
@@ -276,7 +268,6 @@ macro_rules! module_i2c_driver {
///
/// kernel::i2c_device_table!(
/// I2C_TABLE,
-/// MODULE_I2C_TABLE,
/// <MyDriver as i2c::Driver>::IdInfo,
/// [
/// (i2c::DeviceId::new(c"rust_driver_i2c"), ())
@@ -285,7 +276,6 @@ macro_rules! module_i2c_driver {
///
/// kernel::of_device_table!(
/// OF_TABLE,
-/// MODULE_OF_TABLE,
/// <MyDriver as i2c::Driver>::IdInfo,
/// [
/// (of::DeviceId::new(c"test,device"), ())
diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index 3ca99db5cccf22..1e86b901c391bd 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -800,62 +800,6 @@ const fn as_int(&self) -> u32 {
/// }
/// # }
/// ```
-///
-/// This expands to the following code:
-///
-/// ```ignore
-/// use kernel::net::phy::{self, DeviceId};
-/// use kernel::prelude::*;
-///
-/// struct Module {
-/// _reg: ::kernel::net::phy::Registration,
-/// }
-///
-/// module! {
-/// type: Module,
-/// name: "rust_sample_phy",
-/// authors: ["Rust for Linux Contributors"],
-/// description: "Rust sample PHYs driver",
-/// license: "GPL",
-/// }
-///
-/// struct PhySample;
-///
-/// #[vtable]
-/// impl phy::Driver for PhySample {
-/// const NAME: &'static CStr = c"PhySample";
-/// const PHY_DEVICE_ID: phy::DeviceId = phy::DeviceId::new_with_exact_mask(0x00000001);
-/// }
-///
-/// const _: () = {
-/// static mut DRIVERS: [::kernel::net::phy::DriverVTable; 1] =
-/// [::kernel::net::phy::create_phy_driver::<PhySample>()];
-///
-/// impl ::kernel::Module for Module {
-/// fn init(module: &'static ::kernel::ThisModule) -> Result<Self> {
-/// let drivers = unsafe { &mut DRIVERS };
-/// let mut reg = ::kernel::net::phy::Registration::register(
-/// module,
-/// ::core::pin::Pin::static_mut(drivers),
-/// )?;
-/// Ok(Module { _reg: reg })
-/// }
-/// }
-/// };
-///
-/// const N: usize = 1;
-///
-/// const TABLE: ::kernel::device_id::IdArray<::kernel::net::phy::DeviceId, (), N> =
-/// ::kernel::device_id::IdArray::new_without_index([
-/// ::kernel::net::phy::DeviceId(
-/// ::kernel::bindings::mdio_device_id {
-/// phy_id: 0x00000001,
-/// phy_id_mask: 0xffffffff,
-/// }),
-/// ]);
-///
-/// ::kernel::module_device_table!("mdio", phydev, TABLE);
-/// ```
#[macro_export]
macro_rules! module_phy_driver {
(@replace_expr $_t:tt $sub:expr) => {$sub};
@@ -865,12 +809,10 @@ macro_rules! module_phy_driver {
};
(@device_table [$($dev:expr),+]) => {
- const N: usize = $crate::module_phy_driver!(@count_devices $($dev),+);
-
- const TABLE: $crate::device_id::IdArray<$crate::net::phy::DeviceId, (), N> =
- $crate::device_id::IdArray::new_without_index([ $(($dev,())),+, ]);
-
- $crate::module_device_table!("mdio", phydev, TABLE);
+ $crate::module_device_table!(
+ "mdio", $crate::net::phy::DeviceId,
+ TABLE, @none, [$($dev),+]
+ );
};
(drivers: [$($driver:ident),+ $(,)?], device_table: [$($dev:expr),+ $(,)?], $($f:tt)*) => {
diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs
index 58b20c367f993f..d0318f62afd7c8 100644
--- a/rust/kernel/of.rs
+++ b/rust/kernel/of.rs
@@ -25,10 +25,6 @@ unsafe impl RawDeviceId for DeviceId {
// SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `data` field.
unsafe impl RawDeviceIdIndex for DeviceId {
const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::of_device_id, data);
-
- fn index(&self) -> usize {
- self.0.data as usize
- }
}
impl DeviceId {
@@ -53,13 +49,7 @@ pub const fn new(compatible: &'static CStr) -> Self {
/// Create an OF `IdTable` with an "alias" for modpost.
#[macro_export]
macro_rules! of_device_table {
- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => {
- const $table_name: $crate::device_id::IdArray<
- $crate::of::DeviceId,
- $id_info_type,
- { $table_data.len() },
- > = $crate::device_id::IdArray::new($table_data);
-
- $crate::module_device_table!("of", $module_table_name, $table_name);
+ ($($tt:tt)*) => {
+ $crate::module_device_table!("of", $crate::of::DeviceId, $($tt)*);
};
}
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 5071cae6543fd2..925cf280dae2a9 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -110,7 +110,11 @@ extern "C" fn probe_callback(
// SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct pci_device_id` and
// does not add additional invariants, so it's safe to transmute.
let id = unsafe { &*id.cast::<DeviceId>() };
- let info = T::ID_TABLE.info(id.index());
+
+ // SAFETY: `id` comes from `T::ID_TABLE` which is of type `IdArray<_, T::IdInfo>` or
+ // `pci_device_id_any` which has 0 as driver_data. It can also come from dynamic IDs, which
+ // will ensure that `driver_data` exists in `T::ID_TABLE`.
+ let info = unsafe { id.info_unchecked_opt::<T::IdInfo>() };
from_result(|| {
let data = T::probe(pdev, info);
@@ -233,10 +237,6 @@ unsafe impl RawDeviceId for DeviceId {
// SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.
unsafe impl RawDeviceIdIndex for DeviceId {
const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data);
-
- fn index(&self) -> usize {
- self.0.driver_data
- }
}
/// `IdTable` type for PCI.
@@ -245,14 +245,8 @@ fn index(&self) -> usize {
/// Create a PCI `IdTable` with its alias for modpost.
#[macro_export]
macro_rules! pci_device_table {
- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => {
- const $table_name: $crate::device_id::IdArray<
- $crate::pci::DeviceId,
- $id_info_type,
- { $table_data.len() },
- > = $crate::device_id::IdArray::new($table_data);
-
- $crate::module_device_table!("pci", $module_table_name, $table_name);
+ ($($tt:tt)*) => {
+ $crate::module_device_table!("pci", $crate::pci::DeviceId, $($tt)*);
};
}
@@ -267,7 +261,6 @@ macro_rules! pci_device_table {
///
/// kernel::pci_device_table!(
/// PCI_TABLE,
-/// MODULE_PCI_TABLE,
/// <MyDriver as pci::Driver>::IdInfo,
/// [
/// (
@@ -284,7 +277,7 @@ macro_rules! pci_device_table {
///
/// fn probe<'bound>(
/// _pdev: &'bound pci::Device<Core<'_>>,
-/// _id_info: &'bound Self::IdInfo,
+/// _id_info: Option<&'bound Self::IdInfo>,
/// ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
/// Err(ENODEV)
/// }
@@ -313,7 +306,7 @@ pub trait Driver {
/// attempt to initialize the device here.
fn probe<'bound>(
dev: &'bound Device<device::Core<'_>>,
- id_info: &'bound Self::IdInfo,
+ id_info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
/// PCI driver unbind.
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 9b362e0495d323..e12e88113ca5d2 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -100,7 +100,8 @@ extern "C" fn probe_callback(pdev: *mut bindings::platform_device) -> kernel::ff
//
// INVARIANT: `pdev` is valid for the duration of `probe_callback()`.
let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal<'_>>>() };
- let info = <Self as driver::Adapter>::id_info(pdev.as_ref());
+ // SAFETY: `pdev` matched data is of type `Self::IdInfo`.
+ let info = unsafe { <Self as driver::Adapter>::id_info(pdev.as_ref()) };
from_result(|| {
let data = T::probe(pdev, info);
@@ -176,7 +177,6 @@ macro_rules! module_platform_driver {
///
/// kernel::of_device_table!(
/// OF_TABLE,
-/// MODULE_OF_TABLE,
/// <MyDriver as platform::Driver>::IdInfo,
/// [
/// (of::DeviceId::new(c"test,device"), ())
@@ -185,7 +185,6 @@ macro_rules! module_platform_driver {
///
/// kernel::acpi_device_table!(
/// ACPI_TABLE,
-/// MODULE_ACPI_TABLE,
/// <MyDriver as platform::Driver>::IdInfo,
/// [
/// (acpi::DeviceId::new(c"LNUXBEEF"), ())
diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index 7aff0c82d0afc0..aec7dce0495532 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -89,7 +89,10 @@ extern "C" fn probe_callback(
// does not add additional invariants, so it's safe to transmute.
let id = unsafe { &*id.cast::<DeviceId>() };
- let info = T::ID_TABLE.info(id.index());
+ // SAFETY: `id` comes from `T::ID_TABLE` which is of type `IdArray<_, T::IdInfo>`. It
+ // can also come from dynamic IDs, which will ensure that `driver_data` exists in
+ // `T::ID_TABLE` or is 0.
+ let info = unsafe { id.info_unchecked_opt::<T::IdInfo>() };
let data = T::probe(intf, id, info);
let dev: &device::Device<device::CoreInternal<'_>> = intf.as_ref();
@@ -242,10 +245,6 @@ unsafe impl RawDeviceId for DeviceId {
// SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_info` field.
unsafe impl RawDeviceIdIndex for DeviceId {
const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::usb_device_id, driver_info);
-
- fn index(&self) -> usize {
- self.0.driver_info
- }
}
/// [`IdTable`](kernel::device_id::IdTable) type for USB.
@@ -254,14 +253,8 @@ fn index(&self) -> usize {
/// Create a USB `IdTable` with its alias for modpost.
#[macro_export]
macro_rules! usb_device_table {
- ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => {
- const $table_name: $crate::device_id::IdArray<
- $crate::usb::DeviceId,
- $id_info_type,
- { $table_data.len() },
- > = $crate::device_id::IdArray::new($table_data);
-
- $crate::module_device_table!("usb", $module_table_name, $table_name);
+ ($($tt:tt)*) => {
+ $crate::module_device_table!("usb", $crate::usb::DeviceId, $($tt)*);
};
}
@@ -277,7 +270,6 @@ macro_rules! usb_device_table {
///
/// kernel::usb_device_table!(
/// USB_TABLE,
-/// MODULE_USB_TABLE,
/// <MyDriver as usb::Driver>::IdInfo,
/// [
/// (usb::DeviceId::from_id(0x1234, 0x5678), ()),
@@ -293,7 +285,7 @@ macro_rules! usb_device_table {
/// fn probe<'bound>(
/// _interface: &'bound usb::Interface<Core<'_>>,
/// _id: &usb::DeviceId,
-/// _info: &'bound Self::IdInfo,
+/// _info: Option<&'bound Self::IdInfo>,
/// ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
/// Err(ENODEV)
/// }
@@ -322,7 +314,7 @@ pub trait Driver {
fn probe<'bound>(
interface: &'bound Interface<device::Core<'_>>,
id: &DeviceId,
- id_info: &'bound Self::IdInfo,
+ id_info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
/// USB driver disconnect.
diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs
index 1f59e08aaa4b0d..181fd98ae5b663 100644
--- a/samples/rust/rust_debugfs.rs
+++ b/samples/rust/rust_debugfs.rs
@@ -110,7 +110,6 @@ fn from_str(s: &str) -> Result<Self> {
kernel::acpi_device_table!(
ACPI_TABLE,
- MODULE_ACPI_TABLE,
<RustDebugFs as platform::Driver>::IdInfo,
[(acpi::DeviceId::new(c"LNUXBEEF"), ())]
);
diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs
index 5046b4628d0e29..80c309ce07e93e 100644
--- a/samples/rust/rust_dma.rs
+++ b/samples/rust/rust_dma.rs
@@ -51,7 +51,6 @@ unsafe impl kernel::transmute::FromBytes for MyStruct {}
kernel::pci_device_table!(
PCI_TABLE,
- MODULE_PCI_TABLE,
<DmaSampleDriver as pci::Driver>::IdInfo,
[(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
);
@@ -63,7 +62,7 @@ impl pci::Driver for DmaSampleDriver {
fn probe<'bound>(
pdev: &'bound pci::Device<Core<'_>>,
- _info: &'bound Self::IdInfo,
+ _info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self, Error> + 'bound {
pin_init::pin_init_scope(move || {
dev_info!(pdev, "Probe DMA test driver.\n");
diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driver_auxiliary.rs
index 2c1351040e45e5..704567a072bac3 100644
--- a/samples/rust/rust_driver_auxiliary.rs
+++ b/samples/rust/rust_driver_auxiliary.rs
@@ -24,7 +24,6 @@
kernel::auxiliary_device_table!(
AUX_TABLE,
- MODULE_AUX_TABLE,
<AuxiliaryDriver as auxiliary::Driver>::IdInfo,
[(auxiliary::DeviceId::new(MODULE_NAME, AUXILIARY_NAME), ())]
);
@@ -66,7 +65,6 @@ struct ParentData<'bound> {
kernel::pci_device_table!(
PCI_TABLE,
- MODULE_PCI_TABLE,
<ParentDriver as pci::Driver>::IdInfo,
[(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
);
@@ -79,7 +77,7 @@ impl pci::Driver for ParentDriver {
fn probe<'bound>(
pdev: &'bound pci::Device<Core<'_>>,
- _info: &'bound Self::IdInfo,
+ _info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
Ok(ParentData {
// SAFETY: `ParentData` is the driver's private data, which is dropped when the
diff --git a/samples/rust/rust_driver_i2c.rs b/samples/rust/rust_driver_i2c.rs
index ead8263a7d489a..a0df0c6097c4f5 100644
--- a/samples/rust/rust_driver_i2c.rs
+++ b/samples/rust/rust_driver_i2c.rs
@@ -14,21 +14,18 @@
kernel::acpi_device_table! {
ACPI_TABLE,
- MODULE_ACPI_TABLE,
<SampleDriver as i2c::Driver>::IdInfo,
[(acpi::DeviceId::new(c"LNUXBEEF"), 0)]
}
kernel::i2c_device_table! {
I2C_TABLE,
- MODULE_I2C_TABLE,
<SampleDriver as i2c::Driver>::IdInfo,
[(i2c::DeviceId::new(c"rust_driver_i2c"), 0)]
}
kernel::of_device_table! {
OF_TABLE,
- MODULE_OF_TABLE,
<SampleDriver as i2c::Driver>::IdInfo,
[(of::DeviceId::new(c"test,rust_driver_i2c"), 0)]
}
diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci.rs
index 1aa8197d8698c0..652819dff0824b 100644
--- a/samples/rust/rust_driver_pci.rs
+++ b/samples/rust/rust_driver_pci.rs
@@ -74,12 +74,10 @@ struct SampleDriverData<'bound> {
kernel::pci_device_table!(
PCI_TABLE,
- MODULE_PCI_TABLE,
<SampleDriver as pci::Driver>::IdInfo,
- [(
- pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5),
- TestIndex::NO_EVENTFD
- )]
+ {
+ pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5) => TestIndex::NO_EVENTFD,
+ }
);
impl SampleDriverData<'_> {
@@ -144,7 +142,7 @@ impl pci::Driver for SampleDriver {
fn probe<'bound>(
pdev: &'bound pci::Device<Core<'_>>,
- info: &'bound Self::IdInfo,
+ info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
let vendor = pdev.vendor_id();
dev_dbg!(
@@ -153,6 +151,7 @@ fn probe<'bound>(
vendor,
pdev.device_id()
);
+ let info = info.ok_or(ENODEV)?;
pdev.enable_device_mem()?;
pdev.set_master();
diff --git a/samples/rust/rust_driver_platform.rs b/samples/rust/rust_driver_platform.rs
index ec0d6cac4f570b..710145b3605a21 100644
--- a/samples/rust/rust_driver_platform.rs
+++ b/samples/rust/rust_driver_platform.rs
@@ -87,14 +87,12 @@ struct SampleDriver {
kernel::of_device_table!(
OF_TABLE,
- MODULE_OF_TABLE,
<SampleDriver as platform::Driver>::IdInfo,
[(of::DeviceId::new(c"test,rust-device"), Info(42))]
);
kernel::acpi_device_table!(
ACPI_TABLE,
- MODULE_ACPI_TABLE,
<SampleDriver as platform::Driver>::IdInfo,
[(acpi::DeviceId::new(c"LNUXBEEF"), Info(0))]
);
diff --git a/samples/rust/rust_driver_usb.rs b/samples/rust/rust_driver_usb.rs
index 02bd5085f9bc76..7ef04e177c8094 100644
--- a/samples/rust/rust_driver_usb.rs
+++ b/samples/rust/rust_driver_usb.rs
@@ -19,7 +19,6 @@ struct SampleDriver {
kernel::usb_device_table!(
USB_TABLE,
- MODULE_USB_TABLE,
<SampleDriver as usb::Driver>::IdInfo,
[(usb::DeviceId::from_id(0x1234, 0x5678), ()),]
);
@@ -32,7 +31,7 @@ impl usb::Driver for SampleDriver {
fn probe<'bound>(
intf: &'bound usb::Interface<Core<'_>>,
_id: &usb::DeviceId,
- _info: &'bound Self::IdInfo,
+ _info: Option<&'bound Self::IdInfo>,
) -> impl PinInit<Self, Error> + 'bound {
let dev: &device::Device<Core<'_>> = intf.as_ref();
dev_info!(dev, "Rust USB driver sample probed\n");
diff --git a/samples/rust/rust_i2c_client.rs b/samples/rust/rust_i2c_client.rs
index 2d876f4e3ee0a2..c8a23875ef5bc5 100644
--- a/samples/rust/rust_i2c_client.rs
+++ b/samples/rust/rust_i2c_client.rs
@@ -87,14 +87,12 @@ struct SampleDriver {
kernel::of_device_table!(
OF_TABLE,
- MODULE_OF_TABLE,
<SampleDriver as platform::Driver>::IdInfo,
[(of::DeviceId::new(c"test,rust-device"), ())]
);
kernel::acpi_device_table!(
ACPI_TABLE,
- MODULE_ACPI_TABLE,
<SampleDriver as platform::Driver>::IdInfo,
[(acpi::DeviceId::new(c"LNUXBEEF"), ())]
);
diff --git a/samples/rust/rust_soc.rs b/samples/rust/rust_soc.rs
index 808d58200eb677..f5e5f2f9adf762 100644
--- a/samples/rust/rust_soc.rs
+++ b/samples/rust/rust_soc.rs
@@ -23,14 +23,12 @@ struct SampleSocDriver {
kernel::of_device_table!(
OF_TABLE,
- MODULE_OF_TABLE,
<SampleSocDriver as platform::Driver>::IdInfo,
[(of::DeviceId::new(c"test,rust-device"), ())]
);
kernel::acpi_device_table!(
ACPI_TABLE,
- MODULE_ACPI_TABLE,
<SampleSocDriver as platform::Driver>::IdInfo,
[(acpi::DeviceId::new(c"LNUXBEEF"), ())]
);
|
| 3/2 | 2026/06/29 13:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 18532 output: 31 thoughts: 573 Thoughts: **Refactoring Rust Device ID Table Generation: Fuzzing Strategy** Okay, so I'm looking at this patch and it's making some pretty significant changes to how Rust device ID tables are generated and how driver match data is handled. Essentially, it's a deep dive into the core Rust abstractions for various driver types – PCI, USB, platform, I2C, Auxiliary, and ACPI. Specifically, I see that they're removing the `MODULE_OF_TABLE` arguments from those `_device_table!` macros and tweaking the `IdArray` to store references directly instead of using an index. They've also ripped out `acpi_of_match_device` from a couple of places, and the `probe` signatures in the `pci::Driver` and `usb::Driver` traits are being updated to use `Option` for the `IdInfo`. Plus, they're using `bindings::device_get_match_data` for the `id_info` in the `Adapter` trait. My initial thought is, *yes*, this needs fuzzing. It fundamentally alters how drivers are probed and how they receive their critical match data. If something goes wrong here, drivers could easily crash during probe or, worse, operate with incorrect data. This is right in the critical path. The core of the changes seem to be in macros and the implementation of `IdArray`, but the real action happens during driver probe. I need to focus on the code where the drivers actually get called. Specifically, I should look at the `probe_callback` functions within the respective driver implementations: `pci.rs`, `usb.rs`, `platform.rs`, `i2c.rs`, and `auxiliary.rs`. These are the entry points. Now, can I fuzz these things effectively? Syzkaller doesn't have native Rust driver support *yet*, which is a potential roadblock. However, it *does* support fuzzing PCI, USB, platform, and I2C devices. If I enable Rust support and the sample drivers, I *should* be able to test these code paths. Where are those sample drivers? Right, they're in `samples/rust/`. I'll need to enable `CONFIG_SAMPLES_RUST=y` or the appropriate sample configs to get them built. Let me check the Kconfig. |
| 4/2 | 2026/06/29 13:13 | tool | grepper |
0mArgs:{
"Expression": "config SAMPLE_RUST",
"PathPrefix": "samples/rust/Kconfig"
}Results: {
"Output": "samples/rust/Kconfig=11=if SAMPLES_RUST\nsamples/rust/Kconfig-12-\nsamples/rust/Kconfig:13:config SAMPLE_RUST_CONFIGFS\nsamples/rust/Kconfig-14-\ttristate \"Configfs sample\"\n--\nsamples/rust/Kconfig-23-\nsamples/rust/Kconfig:24:config SAMPLE_RUST_MINIMAL\nsamples/rust/Kconfig-25-\ttristate \"Minimal\"\n--\nsamples/rust/Kconfig-33-\nsamples/rust/Kconfig:34:config SAMPLE_RUST_MISC_DEVICE\nsamples/rust/Kconfig-35-\ttristate \"Misc device\"\n--\nsamples/rust/Kconfig-43-\nsamples/rust/Kconfig:44:config SAMPLE_RUST_PRINT\nsamples/rust/Kconfig-45-\ttristate \"Printing macros\"\n--\nsamples/rust/Kconfig-53-\nsamples/rust/Kconfig:54:config SAMPLE_RUST_DMA\nsamples/rust/Kconfig-55-\ttristate \"DMA Test Driver\"\n--\nsamples/rust/Kconfig-64-\nsamples/rust/Kconfig:65:config SAMPLE_RUST_DEBUGFS\nsamples/rust/Kconfig-66-\ttristate \"DebugFS Test Module\"\n--\nsamples/rust/Kconfig-75-\nsamples/rust/Kconfig:76:config SAMPLE_RUST_DEBUGFS_SCOPED\nsamples/rust/Kconfig-77-\ttristate \"Scoped DebugFS Test Module\"\n--\nsamples/rust/Kconfig-86-\nsamples/rust/Kconfig:87:config SAMPLE_RUST_DRIVER_I2C\nsamples/rust/Kconfig-88-\ttristate \"I2C Driver\"\n--\nsamples/rust/Kconfig-97-\nsamples/rust/Kconfig:98:config SAMPLE_RUST_I2C_CLIENT\nsamples/rust/Kconfig-99-\ttristate \"I2C Client Registration\"\n--\nsamples/rust/Kconfig-109-\nsamples/rust/Kconfig:110:config SAMPLE_RUST_DRIVER_PCI\nsamples/rust/Kconfig-111-\ttristate \"PCI Driver\"\n--\nsamples/rust/Kconfig-120-\nsamples/rust/Kconfig:121:config SAMPLE_RUST_DRIVER_PLATFORM\nsamples/rust/Kconfig-122-\ttristate \"Platform Driver\"\n--\nsamples/rust/Kconfig-130-\nsamples/rust/Kconfig:131:config SAMPLE_RUST_DRIVER_USB\nsamples/rust/Kconfig-132-\ttristate \"USB Driver\"\n--\nsamples/rust/Kconfig-141-\nsamples/rust/Kconfig:142:config SAMPLE_RUST_DRIVER_FAUX\nsamples/rust/Kconfig-143-\ttristate \"Faux Driver\"\n--\nsamples/rust/Kconfig-151-\nsamples/rust/Kconfig:152:config SAMPLE_RUST_DRIVER_AUXILIARY\nsamples/rust/Kconfig-153-\ttristate \"Auxiliary Driver\"\n--\nsamples/rust/Kconfig-163-\nsamples/rust/Kconfig:164:config SAMPLE_RUST_SOC\nsamples/rust/Kconfig-165-\ttristate \"SoC Driver\"\n--\nsamples/rust/Kconfig-174-\nsamples/rust/Kconfig:175:config SAMPLE_RUST_HOSTPROGS\nsamples/rust/Kconfig-176-\tbool \"Host programs\"\n"
} |
| 5/2 | 2026/06/29 13:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 20528 output: 31 thoughts: 222 Thoughts: **Analyzing the Rust Driver Abstraction Patch** Okay, so this patch is clearly diving into the core Rust abstractions used for device drivers, which is always interesting. I see a list of configurations that need to be enabled: `RUST`, `SAMPLES_RUST`, and a bunch of samples related to DMA, I2C, PCI, platform devices, USB, auxiliary drivers, and the System-on-a-Chip. This seems like a pretty comprehensive set of examples, covering a good range of hardware interactions. Now, my immediate thought is to see the bigger picture. I need to understand the impact of these changes. I have to see if any existing drivers out there are already making use of these abstractions. Let's see... I've got a list of some files to check: `drivers/gpu/drm/nova/driver.rs`, `drivers/gpu/drm/tyr/driver.rs`, `drivers/gpu/nova-core/driver.rs`, `drivers/pwm/pwm_th1520.rs`, and `drivers/cpufreq/rcpufreq_dt.rs`. I need to track down the configurations for these drivers and see if they have any interactions with what is in the patch. I need to verify that these files don't use the macros being changed. This will give me a better understanding of the scope and potential for conflicts or regressions. Gotta make sure we don't break anything in the process. Time to dig in and correlate these configs. |
| 6/2 | 2026/06/29 13:13 | tool | grepper |
0mArgs:{
"Expression": "config DRM_NOVA",
"PathPrefix": "drivers/gpu/drm/"
}Results: {
"Output": "drivers/gpu/drm/nova/Kconfig:1:config DRM_NOVA\ndrivers/gpu/drm/nova/Kconfig-2-\ttristate \"Nova DRM driver\"\n"
} |
| 7/2 | 2026/06/29 13:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 21152 output: 53 thoughts: 37 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Deep Dive Incoming: Initial Code Review Thoughts** Alright, time to dig in. Let's see what we've got. The initial focus is on `DRM_TYR`, `NOVA_CORE`, `PWM_TH1520`, and `ARM_DT_CPUFREQ_RUST`. Immediately, I'm thinking about the potential interactions here. `DRM_TYR` suggests display or graphics processing, likely on a `TYR` platform or related technology. `NOVA_CORE`... that's less immediately obvious without context, but the "CORE" implies something fundamental, perhaps a central control or system module related to a project's architecture. `PWM_TH1520` jumps out as a Pulse-Width Modulation implementation related to a `TH1520` device. This tells me we could be looking at power control, dimming, or motor control, possibly something for embedded systems. Finally, `ARM_DT_CPUFREQ_RUST` is the most straightforward: CPU frequency scaling on an ARM system, potentially using a device tree (`DT`) for configuration, and written in Rust. I'm instantly considering how these four relate. Is the display linked to CPU frequency scaling? Is there a display interface using PWM? Are we building on a new Rust framework with a core? I'm already envisioning potential bottlenecks and performance considerations. My mind's running through common issues with frequency scaling and PWM: power consumption trade-offs, response times, potential for display flickering or banding, etc. The use of Rust suggests a focus on memory safety and concurrency, which could be relevant given how power and performance management tends to be. I need to understand how each of these components contributes to the whole system design and what their interfaces are. This initial scan is about setting the stage and anticipating where the real challenges are. |
| 8/2 | 2026/06/29 13:13 | tool | grepper |
0mArgs:{
"Expression": "config (DRM_TYR|NOVA_CORE|PWM_TH1520|ARM_DT_CPUFREQ_RUST)",
"PathPrefix": "drivers/"
}Results: {
"Output": "drivers/gpu/drm/tyr/Kconfig-2-\ndrivers/gpu/drm/tyr/Kconfig:3:config DRM_TYR\ndrivers/gpu/drm/tyr/Kconfig-4-\ttristate \"Tyr (Rust DRM support for ARM Mali CSF-based GPUs)\"\n--\ndrivers/gpu/nova-core/Kconfig:1:config NOVA_CORE\ndrivers/gpu/nova-core/Kconfig-2-\ttristate \"Nova Core GPU driver\"\n--\ndrivers/pwm/Kconfig=762=config PWM_TEGRA\n--\ndrivers/pwm/Kconfig-772-\ndrivers/pwm/Kconfig:773:config PWM_TH1520\ndrivers/pwm/Kconfig-774-\ttristate \"TH1520 PWM support\"\n"
} |
| 9/2 | 2026/06/29 13:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 21854 output: 32 thoughts: 11 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and presented as if it were my own internal monologue: **Investigating CPU Frequency Scaling Options** Alright, I'm digging into frequency scaling mechanisms. We're looking at ways to optimize power consumption and performance, and the possibilities are endless. I'm focusing on the low-level interactions here. One area that's always intrigued me, and needs further attention, is the `rcpufreq_dt` driver. What's the latest with that? I need to understand its relationship to the Device Tree (DT) and how it's interacting with the CPUFreq core. I'm wondering about the specifics of its governor implementations, and whether it's handling frequency transitions optimally. There might be some subtle differences that I need to benchmark against the other drivers. Are we seeing any new patches or features? Any potential issues with specific architectures or SoCs? What is its level of community support and maintenance like? Is it compatible with the newer power management frameworks? I should probably cross-reference that with the relevant kernel documentation and the upstream mailing lists. I should make sure I'm up to speed on the latest changes. My research has been fairly recent, but this is a critical driver for embedded systems and mobile devices. Let's see what the documentation says about that. |
| 10/2 | 2026/06/29 13:13 | tool | grepper |
0mArgs:{
"Expression": "rcpufreq_dt",
"PathPrefix": "drivers/cpufreq/"
}Results: {
"Output": "drivers/cpufreq/Makefile=17=obj-$(CONFIG_CPUFREQ_DT)\t\t+= cpufreq-dt.o\ndrivers/cpufreq/Makefile:18:obj-$(CONFIG_CPUFREQ_DT_RUST)\t\t+= rcpufreq_dt.o\ndrivers/cpufreq/Makefile-19-obj-$(CONFIG_CPUFREQ_DT_PLATDEV)\t+= cpufreq-dt-platdev.o\n"
} |
| 11/2 | 2026/06/29 13:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 22295 output: 34 thoughts: 65 Thoughts: Here's my take on those configurations: **Analyzing Kernel Configuration Parameters** Okay, let's see. We've got a list of kernel configuration options to consider: `DRM_NOVA`, `DRM_TYR`, `NOVA_CORE`, `PWM_TH1520`, and `CPUFREQ_DT_RUST`. I immediately need to establish if `CPUFREQ_DT_RUST` is defined in the kernel. Without that, we can't be sure this is a viable part of the overall design. My next step involves checking the relevant Kconfig files. The initial list is there, time to get to work. |
| 12/2 | 2026/06/29 13:13 | tool | grepper |
0mArgs:{
"Expression": "config CPUFREQ_DT_RUST",
"PathPrefix": "drivers/cpufreq/"
}Results: {
"Output": "drivers/cpufreq/Kconfig=207=config CPUFREQ_DT\n--\ndrivers/cpufreq/Kconfig-218-\ndrivers/cpufreq/Kconfig:219:config CPUFREQ_DT_RUST\ndrivers/cpufreq/Kconfig-220-\ttristate \"Rust based Generic DT based cpufreq driver\"\n"
} |
| 13/2 | 2026/06/29 13:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 22632 output: 32 thoughts: 239 Thoughts: **Analyzing Probe Callbacks in the Kernel** Okay, so I'm trying to get a handle on the configuration landscape here. The first question is, "Are there any other configuration files or relevant structures I'm missing?" Let's start by digging into these `probe_callback` functions. I know I've seen it defined in several places like `rust/kernel/pci.rs`, but I also see it in `rust/kernel/usb.rs`, `rust/kernel/platform.rs`, `rust/kernel/i2c.rs` and `rust/kernel/auxiliary.rs`. Given those files, I should focus my attention on those five instances of the `probe_callback` function specifically: the one in PCI, USB, platform, i2c and auxiliary files. However, I need to remember that since this is an `extern "C"` function, the name in the compiled binary might be a bit tricky. It could be mangled during the linking process, or possibly even be statically linked, so I'll need to double check the exact definitions. |
| 14/2 | 2026/06/29 13:13 | tool | grepper |
0mArgs:{
"Expression": "extern \"C\" fn probe_callback",
"PathPrefix": "rust/kernel/"
}Results: {
"Output": "rust/kernel/auxiliary.rs=82=impl\u003cT: Driver\u003e Adapter\u003cT\u003e {\nrust/kernel/auxiliary.rs:83: extern \"C\" fn probe_callback(\nrust/kernel/auxiliary.rs-84- adev: *mut bindings::auxiliary_device,\n--\nrust/kernel/error.rs=499=pub fn from_err_ptr\u003cT\u003e(ptr: *mut T) -\u003e Result\u003c*mut T\u003e {\n--\nrust/kernel/error.rs-534-/// # use kernel::bindings;\nrust/kernel/error.rs:535:/// unsafe extern \"C\" fn probe_callback(\nrust/kernel/error.rs-536-/// pdev: *mut bindings::platform_device,\n--\nrust/kernel/i2c.rs=144=impl\u003cT: Driver\u003e Adapter\u003cT\u003e {\nrust/kernel/i2c.rs:145: extern \"C\" fn probe_callback(idev: *mut bindings::i2c_client) -\u003e kernel::ffi::c_int {\nrust/kernel/i2c.rs-146- // SAFETY: The I2C bus only ever calls the probe callback with a valid pointer to a\n--\nrust/kernel/net/phy.rs=308=impl\u003cT: Driver\u003e Adapter\u003cT\u003e {\n--\nrust/kernel/net/phy.rs-325- /// `phydev` must be passed by the corresponding callback in `phy_driver`.\nrust/kernel/net/phy.rs:326: unsafe extern \"C\" fn probe_callback(phydev: *mut bindings::phy_device) -\u003e c_int {\nrust/kernel/net/phy.rs-327- from_result(|| {\n--\nrust/kernel/pci.rs=99=impl\u003cT: Driver\u003e Adapter\u003cT\u003e {\nrust/kernel/pci.rs:100: extern \"C\" fn probe_callback(\nrust/kernel/pci.rs-101- pdev: *mut bindings::pci_dev,\n--\nrust/kernel/platform.rs=96=impl\u003cT: Driver\u003e Adapter\u003cT\u003e {\nrust/kernel/platform.rs:97: extern \"C\" fn probe_callback(pdev: *mut bindings::platform_device) -\u003e kernel::ffi::c_int {\nrust/kernel/platform.rs-98- // SAFETY: The platform bus only ever calls the probe callback with a valid pointer to a\n--\nrust/kernel/usb.rs=76=impl\u003cT: Driver\u003e Adapter\u003cT\u003e {\nrust/kernel/usb.rs:77: extern \"C\" fn probe_callback(\nrust/kernel/usb.rs-78- intf: *mut bindings::usb_interface,\n"
} |
| 15/2 | 2026/06/29 13:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 23812 output: 26 thoughts: 135 Thoughts: **Analyzing Function Symbol Visibility** Okay, so I'm thinking about how to effectively present function symbols related to our drivers. We've got `probe_callback` nested within the `Adapter<T>` structure. Crucially, these are generic over `T: Driver`, meaning they'll be instantiated separately for each specific driver implementation. That's going to lead to mangled symbol names, something like `*Adapter*probe_callback*`. But that's not going to be helpful to the user. Listing the generic function itself, or these potentially multiply instantiated versions, is a recipe for confusion and difficulty in matching them to the drivers people are actually using. It will be much clearer to just show the entry point for the probe. So, instead of the mangled names, let's focus on the `probe` functions of the *sample* drivers. Listing `SampleDriver::probe`, `DmaSampleDriver::probe`, etc. would be far more intuitive. It directly maps the code back to the concrete drivers. Let me take a look at `samples/rust/rust_driver_pci.rs` to make sure the sample drivers provide this function. |
| 16/2 | 2026/06/29 13:13 | tool | grepper |
0mArgs:{
"Expression": "fn probe",
"PathPrefix": "samples/rust/"
}Results: {
"Output": "samples/rust/rust_debugfs.rs=117=impl platform::Driver for RustDebugFs {\n--\nsamples/rust/rust_debugfs.rs-122-\nsamples/rust/rust_debugfs.rs:123: fn probe\u003c'bound\u003e(\nsamples/rust/rust_debugfs.rs-124- pdev: \u0026'bound platform::Device\u003cCore\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_dma.rs=58=impl pci::Driver for DmaSampleDriver {\n--\nsamples/rust/rust_dma.rs-62-\nsamples/rust/rust_dma.rs:63: fn probe\u003c'bound\u003e(\nsamples/rust/rust_dma.rs-64- pdev: \u0026'bound pci::Device\u003cCore\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_driver_auxiliary.rs=31=impl auxiliary::Driver for AuxiliaryDriver {\n--\nsamples/rust/rust_driver_auxiliary.rs-36-\nsamples/rust/rust_driver_auxiliary.rs:37: fn probe\u003c'bound\u003e(\nsamples/rust/rust_driver_auxiliary.rs-38- adev: \u0026'bound auxiliary::Device\u003cCore\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_driver_auxiliary.rs=72=impl pci::Driver for ParentDriver {\n--\nsamples/rust/rust_driver_auxiliary.rs-77-\nsamples/rust/rust_driver_auxiliary.rs:78: fn probe\u003c'bound\u003e(\nsamples/rust/rust_driver_auxiliary.rs-79- pdev: \u0026'bound pci::Device\u003cCore\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_driver_i2c.rs=33=impl i2c::Driver for SampleDriver {\n--\nsamples/rust/rust_driver_i2c.rs-40-\nsamples/rust/rust_driver_i2c.rs:41: fn probe\u003c'bound\u003e(\nsamples/rust/rust_driver_i2c.rs-42- idev: \u0026'bound i2c::I2cClient\u003cCore\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_driver_pci.rs=137=impl pci::Driver for SampleDriver {\n--\nsamples/rust/rust_driver_pci.rs-142-\nsamples/rust/rust_driver_pci.rs:143: fn probe\u003c'bound\u003e(\nsamples/rust/rust_driver_pci.rs-144- pdev: \u0026'bound pci::Device\u003cCore\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_driver_platform.rs=100=impl platform::Driver for SampleDriver {\n--\nsamples/rust/rust_driver_platform.rs-105-\nsamples/rust/rust_driver_platform.rs:106: fn probe\u003c'bound\u003e(\nsamples/rust/rust_driver_platform.rs-107- pdev: \u0026'bound platform::Device\u003cCore\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_driver_usb.rs=26=impl usb::Driver for SampleDriver {\n--\nsamples/rust/rust_driver_usb.rs-30-\nsamples/rust/rust_driver_usb.rs:31: fn probe\u003c'bound\u003e(\nsamples/rust/rust_driver_usb.rs-32- intf: \u0026'bound usb::Interface\u003cCore\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_i2c_client.rs=105=impl platform::Driver for SampleDriver {\n--\nsamples/rust/rust_i2c_client.rs-110-\nsamples/rust/rust_i2c_client.rs:111: fn probe\u003c'bound\u003e(\nsamples/rust/rust_i2c_client.rs-112- pdev: \u0026'bound platform::Device\u003cdevice::Core\u003c'_\u003e\u003e,\n--\nsamples/rust/rust_soc.rs=36=impl platform::Driver for SampleSocDriver {\n--\nsamples/rust/rust_soc.rs-41-\nsamples/rust/rust_soc.rs:42: fn probe\u003c'bound\u003e(\nsamples/rust/rust_soc.rs-43- pdev: \u0026'bound platform::Device\u003cCore\u003c'_\u003e\u003e,\n"
} |
| 17/2 | 2026/06/29 13:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 25234 output: 55 thoughts: 845 Thoughts: **Focus Symbol Conundrum and Config Verification** Okay, so I'm looking at how to best integrate these Rust driver changes with the fuzzer, specifically considering `FocusSymbols`. My initial thought was to use the `probe` functions from the sample drivers as targets. However, the issue is that syzkaller relies on symbol names, and Rust uses name mangling. For instance, `rust_driver_pci::SampleDriver::probe` becomes something unreadable. I'm questioning whether syzkaller even *supports* Rust demangling or matching. I could provide either name, mangled or demangled, but the safest approach is the exact name if available. Or, perhaps, I should just rely on the fact that changes were made in `rust/kernel/pci.rs` and other similar files. I thought about `IdArray::new` and `IdArray::new_without_index` as possibilities, but these are `const fn` and evaluated at compile-time, so they won't even be in the binary, right? Then I went through the runtime functions that were modified. From `rust/kernel/device_id.rs` it's `info_unchecked`, `info_unchecked_opt`. These are marked as `unsafe fn` and likely inlined. In `rust/kernel/driver.rs`, I'm seeing `id_info`, also `unsafe fn` and likely inlined. Now the interesting ones: `probe_callback` in `rust/kernel/pci.rs`, `rust/kernel/usb.rs`, `rust/kernel/platform.rs`, `rust/kernel/i2c.rs`, and `rust/kernel/auxiliary.rs`. Okay, let's see how `probe_callback` is exported. It's passed as a function pointer to C code, like in `rust/kernel/pci.rs`, so it's *definitely* in the binary. The mangled name is going to be something cryptic like `_ZN...probe_callback...E`. Given the mangling, it seems challenging to get the exact name without digging deeper. Maybe I shouldn't specify `FocusSymbols` for these Rust generic functions, or just omit `FocusSymbols` completely. If I skip `FocusSymbols`, the fuzzer will still hit these code paths naturally if reachable, so that makes things easier. Let's do a quick scan for non-generic functions. I see `acpi_of_match_device` in `drivers/acpi/bus.c` changed to `static`, and the removal of `rust_helper_acpi_of_match_device`, so no new C functions are added. Now for the configs: I need to consider what to enable. The ones I've listed are `RUST`, `SAMPLES_RUST`, `SAMPLE_RUST_DMA`, `SAMPLE_RUST_DRIVER_I2C`, `SAMPLE_RUST_I2C_CLIENT`, `SAMPLE_RUST_DRIVER_PCI`, `SAMPLE_RUST_DRIVER_PLATFORM`, `SAMPLE_RUST_DRIVER_USB`, `SAMPLE_RUST_DRIVER_AUXILIARY`, `SAMPLE_RUST_SOC`, `DRM_NOVA`, `DRM_TYR`, `NOVA_CORE`, `PWM_TH1520`, and `CPUFREQ_DT_RUST`. The next step is to quickly verify that `DRM_NOVA`, `DRM_TYR`, `NOVA_CORE`, `PWM_TH1520`, and `CPUFREQ_DT_RUST` are actually present in the tree and can be enabled. |
| 18/2 | 2026/06/29 13:14 | tool | grepper |
0mArgs:{
"Expression": "config (DRM_NOVA|DRM_TYR|NOVA_CORE|PWM_TH1520|CPUFREQ_DT_RUST)",
"PathPrefix": ""
}Results: {
"Output": "drivers/cpufreq/Kconfig=207=config CPUFREQ_DT\n--\ndrivers/cpufreq/Kconfig-218-\ndrivers/cpufreq/Kconfig:219:config CPUFREQ_DT_RUST\ndrivers/cpufreq/Kconfig-220-\ttristate \"Rust based Generic DT based cpufreq driver\"\n--\ndrivers/gpu/drm/nova/Kconfig:1:config DRM_NOVA\ndrivers/gpu/drm/nova/Kconfig-2-\ttristate \"Nova DRM driver\"\n--\ndrivers/gpu/drm/tyr/Kconfig-2-\ndrivers/gpu/drm/tyr/Kconfig:3:config DRM_TYR\ndrivers/gpu/drm/tyr/Kconfig-4-\ttristate \"Tyr (Rust DRM support for ARM Mali CSF-based GPUs)\"\n--\ndrivers/gpu/nova-core/Kconfig:1:config NOVA_CORE\ndrivers/gpu/nova-core/Kconfig-2-\ttristate \"Nova Core GPU driver\"\n--\ndrivers/pwm/Kconfig=762=config PWM_TEGRA\n--\ndrivers/pwm/Kconfig-772-\ndrivers/pwm/Kconfig:773:config PWM_TH1520\ndrivers/pwm/Kconfig-774-\ttristate \"TH1520 PWM support\"\n"
} |
| 19/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 27256 output: 27 thoughts: 13 Thoughts: Okay, here's my summary, presented as a stream of thought: **Rust Driver Landscape Assessment** Yes, that's absolutely right. The initial assessment confirms the need to evaluate available Rust drivers. My primary goal is to determine the current maturity and availability of drivers specifically written in Rust. So, now, the real question is, are there any other Rust drivers out there? I need to build a comprehensive picture to understand the potential of leveraging this language for our requirements. Time to dig in and see what the landscape actually looks like. |
| 20/2 | 2026/06/29 13:14 | tool | grepper |
0mArgs:{
"Expression": "module_pci_driver!",
"PathPrefix": ""
}Results: {
"Output": "rust/kernel/pci.rs=127= extern \"C\" fn remove_callback(pdev: *mut bindings::pci_dev) {\n--\nrust/kernel/pci.rs-147-///```ignore\nrust/kernel/pci.rs:148:/// kernel::module_pci_driver! {\nrust/kernel/pci.rs-149-/// type: MyDriver,\n--\nrust/macros/module.rs=428=pub(crate) fn module(info: ModuleInfo) -\u003e Result\u003cTokenStream\u003e {\n--\nrust/macros/module.rs-516- /// The `LocalModule` type is the type of the module created by `module!`,\nrust/macros/module.rs:517: /// `module_pci_driver!`, `module_platform_driver!`, etc.\nrust/macros/module.rs-518- type LocalModule = #type_;\n--\nsamples/rust/rust_dma.rs=110= fn drop(self: Pin\u003c\u0026mut Self\u003e) {\n--\nsamples/rust/rust_dma.rs-125-\nsamples/rust/rust_dma.rs:126:kernel::module_pci_driver! {\nsamples/rust/rust_dma.rs-127- type: DmaSampleDriver,\n--\nsamples/rust/rust_driver_pci.rs=182= fn drop(\u0026mut self) {\n--\nsamples/rust/rust_driver_pci.rs-186-\nsamples/rust/rust_driver_pci.rs:187:kernel::module_pci_driver! {\nsamples/rust/rust_driver_pci.rs-188- type: SampleDriver,\n"
} |
| 21/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 27843 output: 26 thoughts: 12 Thoughts: Here's my take on the thought process, as if it were my own: **Diving into the `module_platform_driver!` Macro** Okay, time to dissect `module_platform_driver!`. Let's see what's really happening under the hood. I need to understand its expansion and how it interacts with the platform driver infrastructure in the kernel. I already know the basics, but I need to solidify my understanding of the macro's specific role. I want to see how it registers the driver, handles probe/remove functions, and likely manages the driver's lifetime within the platform bus system. I expect it's a convenience macro, but I want to understand the convenience factor is implemented under the hood. I'm looking for the registration process, how device matching is handled, and what mechanisms are used for resource management within the driver. Let's see how much boilerplate it abstracts and what remains exposed. This should be a quick one! |
| 22/2 | 2026/06/29 13:14 | tool | grepper |
0mArgs:{
"Expression": "module_platform_driver!",
"PathPrefix": ""
}Results: {
"Output": "drivers/cpufreq/rcpufreq_dt.rs=206= fn probe\u003c'bound\u003e(\n--\ndrivers/cpufreq/rcpufreq_dt.rs-214-\ndrivers/cpufreq/rcpufreq_dt.rs:215:module_platform_driver! {\ndrivers/cpufreq/rcpufreq_dt.rs-216- type: CPUFreqDTDriver,\n--\ndrivers/gpu/drm/tyr/tyr.rs-15-\ndrivers/gpu/drm/tyr/tyr.rs:16:kernel::module_platform_driver! {\ndrivers/gpu/drm/tyr/tyr.rs-17- type: TyrPlatformDriver,\n--\nrust/kernel/platform.rs=137= fn acpi_id_table() -\u003e Option\u003cacpi::IdTable\u003cSelf::IdInfo\u003e\u003e {\n--\nrust/kernel/platform.rs-146-/// ```ignore\nrust/kernel/platform.rs:147:/// kernel::module_platform_driver! {\nrust/kernel/platform.rs-148-/// type: MyDriver,\n--\nrust/kernel/pwm.rs=734=macro_rules! module_pwm_platform_driver {\nrust/kernel/pwm.rs-735- ($($user_args:tt)*) =\u003e {\nrust/kernel/pwm.rs:736: $crate::module_platform_driver! {\nrust/kernel/pwm.rs-737- $($user_args)*\n--\nrust/macros/module.rs=428=pub(crate) fn module(info: ModuleInfo) -\u003e Result\u003cTokenStream\u003e {\n--\nrust/macros/module.rs-516- /// The `LocalModule` type is the type of the module created by `module!`,\nrust/macros/module.rs:517: /// `module_pci_driver!`, `module_platform_driver!`, etc.\nrust/macros/module.rs-518- type LocalModule = #type_;\n--\nsamples/rust/rust_debugfs.rs-57-\nsamples/rust/rust_debugfs.rs:58:kernel::module_platform_driver! {\nsamples/rust/rust_debugfs.rs-59- type: RustDebugFs,\n--\nsamples/rust/rust_driver_platform.rs=181= fn drop(\u0026mut self) {\n--\nsamples/rust/rust_driver_platform.rs-185-\nsamples/rust/rust_driver_platform.rs:186:kernel::module_platform_driver! {\nsamples/rust/rust_driver_platform.rs-187- type: SampleDriver,\n--\nsamples/rust/rust_i2c_client.rs=131= fn unbind\u003c'bound\u003e(\n--\nsamples/rust/rust_i2c_client.rs-141-\nsamples/rust/rust_i2c_client.rs:142:kernel::module_platform_driver! {\nsamples/rust/rust_i2c_client.rs-143- type: SampleDriver,\n--\nsamples/rust/rust_soc.rs=42= fn probe\u003c'bound\u003e(\n--\nsamples/rust/rust_soc.rs-71-\nsamples/rust/rust_soc.rs:72:kernel::module_platform_driver! {\nsamples/rust/rust_soc.rs-73- type: SampleSocDriver,\n"
} |
| 23/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 28930 output: 35 thoughts: 72 Thoughts: Here's my summary, as though I'm thinking through this: **Analyzing the Relevant Drivers and Modules** Okay, let's break this down. My initial assessment points to a few key drivers and modules that need closer examination. I see we're dealing with `CPUFREQ_DT_RUST`, which seems straightforward enough – likely relating to CPU frequency scaling and device tree integration, all written in Rust. Then there's `DRM_TYR`, suggesting we're looking at a display driver, and `PWM_TH1520` via `module_pwm_platform_driver!`, which probably deals with pulse-width modulation, likely the TH1520 variant. The inclusion of `module_pwm_platform_driver!` is interesting because it suggests a certain platform abstraction layer and how the PWM driver might interact with the system. Now, `DRM_NOVA` is also on the list – could be another display driver, or perhaps auxiliary to `DRM_TYR`. Finally, there's `NOVA_CORE`, flagged as PCI. This one needs a thorough look. My intuition tells me that `NOVA_CORE` is the crucial piece, acting as the core PCI driver for the "NOVA" hardware. I think I'll start there. Understanding `NOVA_CORE` will likely shed light on how all these other drivers, especially the display-related ones, interface and are managed. Let's see what we find. |
| 24/2 | 2026/06/29 13:14 | tool | grepper |
0mError:no matches Args: {
"Expression": "module_pci_driver!",
"PathPrefix": "drivers/gpu/nova-core/"
}Results: {
"error": "no matches"
} |
| 25/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29363 output: 30 thoughts: 22 Thoughts: Here's my thought process, as if I were considering this myself: **Investigating the Nova GPU Driver** Okay, so I need to understand how this `nova` GPU driver interacts with the system. My initial thought is to zero in on `drivers/gpu/nova-core/driver.rs`. That seems like the logical place to start – the "core" directory often houses the essential logic for a driver. My hypothesis is that this file will contain the main driver entry points and, very likely, the definition or usage of a `module_` variable or structure. This is a common pattern in kernel modules. I'll need to check if it's the core module, or possibly a helper module. I'll look for how the kernel is handling this driver module's interaction. |
| 26/2 | 2026/06/29 13:14 | tool | grepper |
0mArgs:{
"Expression": "module_",
"PathPrefix": "drivers/gpu/nova-core/"
}Results: {
"Output": "drivers/gpu/nova-core/firmware.rs=445= pub(crate) const fn create(\ndrivers/gpu/nova-core/firmware.rs:446: module_name: \u0026'static core::ffi::CStr,\ndrivers/gpu/nova-core/firmware.rs-447- ) -\u003e firmware::ModInfoBuilder\u003cN\u003e {\ndrivers/gpu/nova-core/firmware.rs:448: let mut this = Self(firmware::ModInfoBuilder::new(module_name));\ndrivers/gpu/nova-core/firmware.rs-449- let mut i = 0;\n--\ndrivers/gpu/nova-core/nova_core.rs=56= fn init(module: \u0026'static kernel::ThisModule) -\u003e impl PinInit\u003cSelf, Error\u003e {\n--\ndrivers/gpu/nova-core/nova_core.rs-78-\ndrivers/gpu/nova-core/nova_core.rs:79:kernel::module_firmware!(firmware::ModInfoBuilder);\n"
} |
| 27/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29842 output: 30 thoughts: 35 Thoughts: Okay, here's my interpretation of that thought process, from an expert's perspective: **Diving into the `nova_core` Driver Implementation** Right, so I see a reference to `nova_core`... and I immediately assume it's employing a macro, most likely `module!` or something similar given its likely role in a kernel driver. Good place to start. Let's get right to the source. The natural place to look is `drivers/gpu/nova-core/nova_core.rs`. Time to open up that file and start dissecting the implementation. I'm keen to see how they've structured the module and what initialization/management strategies are in play. |
| 28/2 | 2026/06/29 13:14 | tool | grepper |
0mArgs:{
"Expression": "module!",
"PathPrefix": "drivers/gpu/nova-core/"
}Results: {
"Output": "drivers/gpu/nova-core/nova_core.rs=56= fn init(module: \u0026'static kernel::ThisModule) -\u003e impl PinInit\u003cSelf, Error\u003e {\n--\ndrivers/gpu/nova-core/nova_core.rs-69-\ndrivers/gpu/nova-core/nova_core.rs:70:module! {\ndrivers/gpu/nova-core/nova_core.rs-71- type: NovaCoreModule,\n"
} |
| 29/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 30174 output: 28 thoughts: 321 Thoughts: **My Analysis of the Rust-Based Module Configuration** Okay, so this is definitely using `module!`, which is good to know. Now, let me break down these configurations required. We've got `RUST`, `SAMPLES_RUST`, `SAMPLE_RUST_DMA`, `SAMPLE_RUST_DRIVER_I2C`, `SAMPLE_RUST_I2C_CLIENT`, `SAMPLE_RUST_DRIVER_PCI`, `SAMPLE_RUST_DRIVER_PLATFORM`, `SAMPLE_RUST_DRIVER_USB`, `SAMPLE_RUST_DRIVER_AUXILIARY`, and `SAMPLE_RUST_SOC`. That covers a good range of sample drivers. Now, let's look at the display options as we have `DRM_NOVA`, `DRM_TYR`, `NOVA_CORE`. Wait, hold on. I need to make a mental note that `DRM_NOVA` and `NOVA_CORE` inherently depend on `DRM`, so enabling those means `DRM` is implied. Then we have `PWM_TH1520` which requires `PWM`, and then there's `CPUFREQ_DT_RUST` requiring `CPUFREQ_DT`. I2C, PCI, USB, platform and auxiliary are all taken care of in this sample. So, `SAMPLE_RUST_DRIVER_I2C` needs `I2C`, `SAMPLE_RUST_DRIVER_PCI` needs `PCI`, and `SAMPLE_RUST_DRIVER_USB` depends on `USB`. It looks like `SAMPLE_RUST_DRIVER_PLATFORM` is on the platform bus, which should always be on. `SAMPLE_RUST_DRIVER_AUXILIARY` needs `AUXILIARY_BUS`, so that's all. I'm wondering if there are any other Rust-based drivers that need to be considered in addition to these samples. |
| 30/2 | 2026/06/29 13:14 | tool | grepper |
0mArgs:{
"Expression": "module_i2c_driver!",
"PathPrefix": ""
}Results: {
"Output": "rust/kernel/i2c.rs=225= fn acpi_id_table() -\u003e Option\u003cacpi::IdTable\u003cSelf::IdInfo\u003e\u003e {\n--\nrust/kernel/i2c.rs-234-/// ```ignore\nrust/kernel/i2c.rs:235:/// kernel::module_i2c_driver! {\nrust/kernel/i2c.rs-236-/// type: MyDriver,\n--\nsamples/rust/rust_driver_i2c.rs=60= fn unbind\u003c'bound\u003e(idev: \u0026'bound i2c::I2cClient\u003cCore\u003c'_\u003e\u003e, _this: Pin\u003c\u0026Self\u003e) {\n--\nsamples/rust/rust_driver_i2c.rs-64-\nsamples/rust/rust_driver_i2c.rs:65:kernel::module_i2c_driver! {\nsamples/rust/rust_driver_i2c.rs-66- type: SampleDriver,\n"
} |
| 31/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 31180 output: 26 thoughts: 10 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person: **Initial Assessment of USB Driver Implementation** Right, so I'm thinking about this USB driver implementation... and the immediate question that pops into my head is: what's the deal with `module_usb_driver!`? That macro or function, whatever it's defined as, is the crucial entry point, isn't it? It's where the rubber meets the road, where the kernel and our driver are linked. I need to understand that piece first. Is it used to register the driver? Describe the interfaces the USB device supports? Or is it more involved than that? What are the implications of the name? Is it a rust specific thing, or is it common in other languages? What's the context where I find it used? Are there any obvious gotchas? I need to analyze its structure. Is it a compile-time mechanism, linking a driver statically or dynamically? Or does it perform runtime registration? Depending on the architecture, it could be a simple interface. If I understand that macro's function then the rest of the code will make more sense. My understanding of that macro is key. |
| 32/2 | 2026/06/29 13:14 | tool | grepper |
0mArgs:{
"Expression": "module_usb_driver!",
"PathPrefix": ""
}Results: {
"Output": "rust/kernel/usb.rs=472=unsafe impl Sync for Device\u003cdevice::Bound\u003e {}\n--\nrust/kernel/usb.rs-478-/// ```ignore\nrust/kernel/usb.rs:479:/// module_usb_driver! {\nrust/kernel/usb.rs-480-/// type: MyDriver,\n--\nsamples/rust/rust_driver_usb.rs=42= fn disconnect\u003c'bound\u003e(intf: \u0026'bound usb::Interface\u003cCore\u003c'_\u003e\u003e, _data: Pin\u003c\u0026Self\u003e) {\n--\nsamples/rust/rust_driver_usb.rs-47-\nsamples/rust/rust_driver_usb.rs:48:kernel::module_usb_driver! {\nsamples/rust/rust_driver_usb.rs-49- type: SampleDriver,\n"
} |
| 33/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 31677 output: 27 thoughts: 11 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and presented as if it's my own internal dialogue: **Investigating a Code Architecture Element** Hmm, I'm just considering a specific point within this architecture. What's the deal with `module_auxiliary_driver!`? It immediately jumps out. Is it a central component, a utility, or a more obscure part of the overall flow? I'm wondering about its purpose, its potential for reuse, and if it could become a bottleneck or a point of critical failure. I need to understand its role within the system. Is there a better way? Perhaps it should be refactored, or improved? |
| 34/2 | 2026/06/29 13:14 | tool | grepper |
0mArgs:{
"Expression": "module_auxiliary_driver!",
"PathPrefix": ""
}Results: {
"Output": "drivers/gpu/drm/nova/nova.rs-10-\ndrivers/gpu/drm/nova/nova.rs:11:kernel::module_auxiliary_driver! {\ndrivers/gpu/drm/nova/nova.rs-12- type: NovaDriver,\n"
} |
| 35/2 | 2026/06/29 13:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 31939 output: 31 thoughts: 26 Thoughts: Here's my take on the thought process, as if it were my own: **Rust Driver Module Dive** Okay, hold on a second. I'm reviewing this Rust code, and I've just landed on `samples/rust/rust_driver_auxiliary.rs`. And what's this? I'm seeing a `module_auxiliary_driver!` macro invocation. Interesting. I need to understand why this specific auxiliary file is leveraging a driver macro and, by extension, where else this design decision may present. I wonder if there are more nuanced behaviors that should influence further work. I need to quickly recall the general pattern of this module design... right, the intention here is likely to define the driver logic in a modular and reusable way, presumably for managing some auxiliary functionality related to the main driver or to reduce code duplication and enhance maintainability, perhaps within a larger architectural context. I need to dig into `module_auxiliary_driver!` and trace its usage to confirm my initial hypothesis and determine exactly what auxiliary functionality it's orchestrating here. It's time to follow the macro trail. |
| 36/2 | 2026/06/29 13:15 | tool | grepper |
0mError:no matches Args: {
"Expression": "module_auxiliary_driver!",
"PathPrefix": "samples/rust/"
}Results: {
"error": "no matches"
} |
| 37/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 32242 output: 34 thoughts: 18 Thoughts: Here's a summary of my thought process: **Diving into the Auxiliary Rust Driver Code** Okay, time to get my hands dirty. I need to understand this Rust driver auxiliary code. Let's start by looking at `samples/rust/rust_driver_auxiliary.rs`. This file is likely providing critical supporting functions or structures for the main driver. I'll need to analyze its role within the broader driver architecture, identifying its core responsibilities. I'll be looking for things like initialization routines, data structure definitions, helper functions, and error handling mechanisms. Understanding this auxiliary code is crucial for a complete grasp of how the Rust driver functions. Let's see what we can find. |
| 38/2 | 2026/06/29 13:15 | tool | grepper |
0mArgs:{
"Expression": "module!",
"PathPrefix": "samples/rust/rust_driver_auxiliary.rs"
}Results: {
"Output": "samples/rust/rust_driver_auxiliary.rs=146= fn init(module: \u0026'static kernel::ThisModule) -\u003e impl PinInit\u003cSelf, Error\u003e {\n--\nsamples/rust/rust_driver_auxiliary.rs-153-\nsamples/rust/rust_driver_auxiliary.rs:154:module! {\nsamples/rust/rust_driver_auxiliary.rs-155- type: SampleModule,\n"
} |
| 39/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 32559 output: 26 thoughts: 208 Thoughts: **Analyzing the Configuration Structure** Alright, I see this configuration is using `module!` to define its structure. That's a familiar pattern. Let me quickly run through the enabled configurations to get a feel for the scope. Okay, here's the list: `RUST`, `SAMPLES_RUST`, `SAMPLE_RUST_DMA`, `SAMPLE_RUST_DRIVER_I2C`, `SAMPLE_RUST_I2C_CLIENT`, `SAMPLE_RUST_DRIVER_PCI`, `SAMPLE_RUST_DRIVER_PLATFORM`, `SAMPLE_RUST_DRIVER_USB`, `SAMPLE_RUST_DRIVER_AUXILIARY`, `SAMPLE_RUST_SOC`, `DRM_NOVA`, `DRM_TYR`, `NOVA_CORE`, `PWM_TH1520`, `CPUFREQ_DT_RUST`, and `AUXILIARY_BUS`. Hmm, it's a pretty diverse set, covering drivers, samples, and SoC-specific elements. Wait a second, I need to double-check something. Seeing `AUXILIARY_BUS` in there raises a flag. I recall that being a boolean or tristate configuration value. It's a common area for errors in these setups. I need to make sure the name and use are correct here, considering its potential to influence a number of dependent configurations. Let me quickly verify that the name is appropriate, given the context. |
| 40/2 | 2026/06/29 13:15 | tool | grepper |
0mArgs:{
"Expression": "config AUXILIARY_BUS",
"PathPrefix": ""
}Results: {
"Output": "drivers/base/Kconfig=2=menu \"Generic Driver Options\"\ndrivers/base/Kconfig-3-\ndrivers/base/Kconfig:4:config AUXILIARY_BUS\ndrivers/base/Kconfig-5-\tbool\n"
} |
| 41/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 33164 output: 34 thoughts: 215 Thoughts: **Analyzing the Code Changes** Okay, so we're looking at modifications related to the `AUXILIARY_BUS`. Got it. Now, what's been specifically altered? Let's see... the core changes seem to be in the `probe` signatures within both `pci::Driver` and `usb::Driver`, and also touches on `IdArray::new` and `IdArray::new_without_index`. That's interesting, suggesting potential adjustments to how device IDs are handled during the probing process. Beyond that, there have been edits to `probe_callback` across `pci.rs`, `usb.rs`, `platform.rs`, `i2c.rs`, and `auxiliary.rs`. And, there are changes to the `id_info` function within the `Adapter` trait. This is likely an improvement to the device matching process across a variety of busses. Finally, there's a modification to `acpi_of_match_device` in `drivers/acpi/bus.c`. Right, let's take a closer look at that one. Ah, it's been changed to `static`. Okay, curious. The obvious question is: where is it called from? Let's check... It seems it's called from `acpi_companion_match` also in `drivers/acpi/bus.c`. Okay, let's go check `acpi_companion_match` to see what is going on. |
| 42/2 | 2026/06/29 13:15 | tool | grepper |
0mArgs:{
"Expression": "acpi_companion_match",
"PathPrefix": "drivers/acpi/bus.c"
}Results: {
"Output": "drivers/acpi/bus.c=850=bool acpi_device_is_first_physical_node(struct acpi_device *adev,\n--\ndrivers/acpi/bus.c-856-/*\ndrivers/acpi/bus.c:857: * acpi_companion_match() - Can we match via ACPI companion device\ndrivers/acpi/bus.c-858- * @dev: Device in question\n--\ndrivers/acpi/bus.c-876- */\ndrivers/acpi/bus.c:877:const struct acpi_device *acpi_companion_match(const struct device *dev)\ndrivers/acpi/bus.c-878-{\n--\ndrivers/acpi/bus.c=1076=const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,\n--\ndrivers/acpi/bus.c-1078-{\ndrivers/acpi/bus.c:1079:\treturn acpi_match_acpi_device(ids, acpi_companion_match(dev));\ndrivers/acpi/bus.c-1080-}\n--\ndrivers/acpi/bus.c=1083=const void *acpi_device_get_match_data(const struct device *dev)\n--\ndrivers/acpi/bus.c-1086-\tconst struct of_device_id *of_ids = dev-\u003edriver-\u003eof_match_table;\ndrivers/acpi/bus.c:1087:\tconst struct acpi_device *adev = acpi_companion_match(dev);\ndrivers/acpi/bus.c-1088-\tconst struct acpi_device_id *acpi_id = NULL;\n--\ndrivers/acpi/bus.c=1111=bool acpi_driver_match_device(struct device *dev,\n--\ndrivers/acpi/bus.c-1119-\ndrivers/acpi/bus.c:1120:\treturn __acpi_match_device(acpi_companion_match(dev), acpi_ids, of_ids, NULL, NULL);\ndrivers/acpi/bus.c-1121-}\n"
} |
| 43/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 34276 output: 33 thoughts: 1066 Thoughts: **Analyzing the Impact of the ACPI/OF Matching Cleanup on Rust Drivers and Fuzzing Strategy** Okay, so I'm looking at this patch and my initial thought is that it's a cleanup, essentially. We're making `acpi_of_match_device` static and removing a Rust helper function, which seems straightforward. The key is that the Rust code now calls `bindings::device_get_match_data` for match data instead of doing the ACPI/OF matching itself, which *is* a functional change that needs careful consideration, and I'm using my experience as a kernel expert to assess. If `device_get_match_data` behaves differently, we could have issues. This function handles a mix of ACPI, OF, and I2C/SPI tables, so the old approach of manual checks in Rust is gone. The core of this logic change is actually in `rust/kernel/driver.rs`, specifically the `id_info` function, which is, importantly, inline. This means it gets compiled directly into each driver's `probe_callback`. Therefore, the critical point for validation is the `probe` functions of the sample drivers. I'll need to confirm that these are all executed. Let's quickly list them: `rust_driver_pci::SampleDriver::probe`, `rust_driver_usb::SampleDriver::probe`, and so on. Now, a related thought occurs: How does this impact our fuzzing strategy? I'm using syzkaller, and I'm immediately concerned about symbol names. Rust mangles symbol names. For example, `SampleDriver::probe` is going to be `_ZN15rust_driver_pci12SampleDriver5probe17h...E`, so providing `SampleDriver::probe` to syzkaller's `FocusSymbols` might not work. Initially, I considered substring matching but then remembered that the syzkaller `FocusSymbols` requires exact matches. Since Rust symbol mangling includes a hash that will change between builds, it seems better to avoid `FocusSymbols` for Rust functions unless we use `#[no_mangle]`. However, now I've noticed `probe_callback` is `extern "C"` but it's generic, so its name is also mangled. Let's see: `acpi_of_match_device` is a C function, but it's now static, which doesn't help with external symbol lookup. `device_get_match_data` is a C function, but it's not modified by this patch, so there's no symbol change. Okay, so the changed C functions are: `acpi_of_match_device` in `drivers/acpi/bus.c` (made static) and removing `rust_helper_acpi_of_match_device` and `rust_helper_to_acpi_device_node`. Given the nature of the changes (macros, inline functions, and the challenges of providing Rust symbols to `FocusSymbols`), it makes sense to leave `FocusSymbols` empty. The fuzzer will still hit the modified code because it's on the `probe` paths of the Rust drivers, and we are enabling the sample drivers. Let's quickly verify my configurations. I've got `RUST`, `SAMPLES_RUST` etc., and all the Rust sample drivers enabled. Wait, I need to make sure I don't miss something. I see `DRM_NOVA`, `DRM_TYR`, and `NOVA_CORE`. These might have dependencies on `DRM`, and other things. So now let's double check `DRM_NOVA` dependencies. I need to make sure all dependencies are set up correctly. |
| 44/2 | 2026/06/29 13:15 | tool | grepper |
0mArgs:{
"Expression": "config DRM_NOVA",
"PathPrefix": "drivers/gpu/drm/nova/"
}Results: {
"Output": "drivers/gpu/drm/nova/Kconfig:1:config DRM_NOVA\ndrivers/gpu/drm/nova/Kconfig-2-\ttristate \"Nova DRM driver\"\n"
} |
| 45/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 36237 output: 36 thoughts: 16 Thoughts: Here's a summary of my thought process, as if I were reading the provided text: **Delving into the Nova DRM Kconfig** Alright, let's dive into this `drivers/gpu/drm/nova/Kconfig` file. Given my expertise, I'm immediately looking for the usual suspects: the overall structure, dependencies, and any potentially interesting configuration options related to the Nova DRM driver. I expect to see a section outlining the core features, maybe things like framebuffer support, display controller functionalities, or power management capabilities. My brain is already running through potential use cases – embedded systems, perhaps specific graphics chips, or maybe it's something more experimental. I'll be searching for clear dependencies on other kernel subsystems, like PCI or I2C, which would give me clues about the hardware this driver is intended for. I'll also be watching for any conditional blocks, `if` statements, or boolean variables. These will show me how various parts of the driver can be enabled or disabled based on build-time configuration, which is the heart of Kconfig. I'm also anticipating the inclusion of module options. Are there ways to tweak certain aspects of the driver, like debugging level or default settings? I know this kind of configuration can make a huge difference, particularly during development or when trying to isolate hardware issues. I'll be keeping an eye out for any unusual or obscure options, things that might hint at a specific hardware quirk or a niche use-case that I need to be aware of. All of this helps to get a broader scope of the Nova DRM and its place within the overall ecosystem. |
| 46/2 | 2026/06/29 13:15 | tool | read-file |
0mArgs:{
"File": "drivers/gpu/drm/nova/Kconfig",
"FirstLine": 1,
"LineCount": 20
}Results: {
"Contents": " 1:\tconfig DRM_NOVA\n 2:\t\ttristate \"Nova DRM driver\"\n 3:\t\tdepends on 64BIT\n 4:\t\tdepends on DRM=y\n 5:\t\tdepends on PCI\n 6:\t\tdepends on RUST\n 7:\t\tdepends on !CPU_BIG_ENDIAN\n 8:\t\tselect AUXILIARY_BUS\n 9:\t\tselect NOVA_CORE\n 10:\t\tdefault n\n 11:\t\thelp\n 12:\t\t Choose this if you want to build the Nova DRM driver for Nvidia\n 13:\t\t GSP-based GPUs.\n 14:\t\n 15:\t\t This driver is work in progress and may not be functional.\n 16:\t\n 17:\t\t If M is selected, the module will be called nova-drm.\n"
} |
| 47/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 36834 output: 37 thoughts: 63 Thoughts: **Analyzing DRM Dependencies** Okay, so I'm looking at the dependencies for `DRM_NOVA`. It's pretty straightforward: it hinges on `DRM=y`, which makes sense, obviously. We also need `PCI`, `RUST`, and importantly, the architecture can't be big-endian, so `!CPU_BIG_ENDIAN`. Got it. That dictates the hardware and some important language requirements. Now, from the look of it, `DRM_NOVA` also automatically enables `AUXILIARY_BUS` and `NOVA_CORE`. Good. That simplifies things a bit; I don't have to trace those down separately right now. Alright, now let's quickly pivot and check the dependencies for `DRM_TYR`. See if there are any interesting overlaps or differences there that might be informative. |
| 48/2 | 2026/06/29 13:15 | tool | read-file |
0mArgs:{
"File": "drivers/gpu/drm/tyr/Kconfig",
"FirstLine": 1,
"LineCount": 20
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0 or MIT\n 2:\t\n 3:\tconfig DRM_TYR\n 4:\t\ttristate \"Tyr (Rust DRM support for ARM Mali CSF-based GPUs)\"\n 5:\t\tdepends on DRM=y\n 6:\t\tdepends on RUST\n 7:\t\tdepends on ARM || ARM64 || COMPILE_TEST\n 8:\t\tdepends on !GENERIC_ATOMIC64 # for IOMMU_IO_PGTABLE_LPAE\n 9:\t\tdepends on COMMON_CLK\n 10:\t\tdefault n\n 11:\t\tselect RUST_DRM_GEM_SHMEM_HELPER\n 12:\t\thelp\n 13:\t\t Rust DRM driver for ARM Mali CSF-based GPUs.\n 14:\t\n 15:\t\t This driver is for Mali (or Immortalis) Valhall Gxxx GPUs.\n 16:\t\n 17:\t\t Note that the Mali-G68 and Mali-G78, while Valhall architecture, will\n 18:\t\t be supported with the panfrost driver as they are not CSF GPUs.\n 19:\t\n 20:\t\t if M is selected, the module will be called tyr. This driver is work\n"
} |
| 49/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 37428 output: 32 thoughts: 15 Thoughts: Here's my take on those thoughts: **Analyzing `PWM_TH1520` Dependencies** Okay, so I need to get a handle on `PWM_TH1520`. Before I do anything else, let's take a good, hard look at its dependencies. What other modules, libraries, or system resources is this thing relying on? Is it tied to any specific hardware or data interfaces? I need to know the ripple effect if I were to change or update this. Are there any known conflicts with existing components? Identifying these dependencies upfront is crucial for understanding its role and potential impact within the system. Let's make sure nothing else will break if I go poking around at this. |
| 50/2 | 2026/06/29 13:15 | tool | grepper |
0mArgs:{
"Expression": "config PWM_TH1520",
"PathPrefix": "drivers/pwm/"
}Results: {
"Output": "drivers/pwm/Kconfig=762=config PWM_TEGRA\n--\ndrivers/pwm/Kconfig-772-\ndrivers/pwm/Kconfig:773:config PWM_TH1520\ndrivers/pwm/Kconfig-774-\ttristate \"TH1520 PWM support\"\n"
} |
| 51/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 37711 output: 34 thoughts: 18 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and presented as if it were my own internal monologue: **Diving into the PWM Configuration** Alright, I'm thinking we need to delve into the `drivers/pwm/Kconfig` file, specifically around line 773. I've got a feeling there's a particular configuration option or conditional statement related to the PWM subsystem that's relevant to whatever issue or investigation is at hand. Given my experience, I'm anticipating that line probably contains a critical dependency or feature-enablement condition I need to understand. I could be looking at a specific device driver's configuration, a generic PWM controller option, or possibly a feature flag affecting how the PWM core behaves. My guess is that it’s probably related to a particular PWM feature or a specific driver that I'm trying to enable or debug. I need to quickly identify the relevant configuration option and understand its dependencies to get to the bottom of this. This is where the action is, so I'm moving there directly. |
| 52/2 | 2026/06/29 13:15 | tool | read-file |
0mArgs:{
"File": "drivers/pwm/Kconfig",
"FirstLine": 770,
"LineCount": 20
}Results: {
"Contents": " 770:\t\t To compile this driver as a module, choose M here: the module\n 771:\t\t will be called pwm-tegra.\n 772:\t\n 773:\tconfig PWM_TH1520\n 774:\t\ttristate \"TH1520 PWM support\"\n 775:\t\tdepends on ARCH_THEAD || COMPILE_TEST\n 776:\t\tdepends on RUST\n 777:\t\tdepends on HAS_IOMEM \u0026\u0026 COMMON_CLK\n 778:\t\tselect RUST_PWM_ABSTRACTIONS\n 779:\t\thelp\n 780:\t\t This option enables the driver for the PWM controller found on the\n 781:\t\t T-HEAD TH1520 SoC.\n 782:\t\n 783:\t\t To compile this driver as a module, choose M here; the module\n 784:\t\t will be called pwm-th1520. If you are unsure, say N.\n 785:\t\n 786:\tconfig PWM_TIECAP\n 787:\t\ttristate \"ECAP PWM support\"\n 788:\t\tdepends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST\n 789:\t\tdepends on HAS_IOMEM\n"
} |
| 53/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 38335 output: 36 thoughts: 15 Thoughts: Here's my take on those thoughts: **Analyzing `CPUFREQ_DT_RUST` Dependencies** Okay, so I need to get a handle on the current state of things related to `CPUFREQ_DT_RUST`. Before I can make any informed decisions or propose any changes, I absolutely have to understand its dependencies. What other modules, crates, or even hardware-specific drivers does this depend on? Are there any upstream projects or libraries that it calls into? I need to understand the complete web of connections. Are there any known issues, like potentially outdated dependencies or specific versions needed? I'm thinking of looking for build configurations or documentation that describes any prerequisites. The goal is to identify potential bottlenecks, incompatibilities, or areas that might require special attention during testing or development. It’s about building a solid foundation of knowledge before I go any further. I'm going to start digging. |
| 54/2 | 2026/06/29 13:15 | tool | read-file |
0mArgs:{
"File": "drivers/cpufreq/Kconfig",
"FirstLine": 215,
"LineCount": 20
}Results: {
"Contents": " 215:\t\t systems.\n 216:\t\n 217:\t\t If in doubt, say N.\n 218:\t\n 219:\tconfig CPUFREQ_DT_RUST\n 220:\t\ttristate \"Rust based Generic DT based cpufreq driver\"\n 221:\t\tdepends on HAVE_CLK \u0026\u0026 OF \u0026\u0026 RUST\n 222:\t\tselect CPUFREQ_DT_PLATDEV\n 223:\t\tselect PM_OPP\n 224:\t\thelp\n 225:\t\t This adds a Rust based generic DT based cpufreq driver for frequency\n 226:\t\t management. It supports both uniprocessor (UP) and symmetric\n 227:\t\t multiprocessor (SMP) systems.\n 228:\t\n 229:\t\t If in doubt, say N.\n 230:\t\n 231:\tconfig CPUFREQ_VIRT\n 232:\t\ttristate \"Virtual cpufreq driver\"\n 233:\t\tdepends on GENERIC_ARCH_TOPOLOGY\n 234:\t\thelp\n"
} |
| 55/2 | 2026/06/29 13:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 38857 output: 26 thoughts: 305 Thoughts: **My Current Thinking About Rust Kernel Configurations** Okay, let's see, I'm looking at the key configurations here. I've got a whole list: `RUST`, `SAMPLES_RUST`, `SAMPLE_RUST_DMA`, and a bunch of drivers: `SAMPLE_RUST_DRIVER_I2C`, `SAMPLE_RUST_I2C_CLIENT`, `SAMPLE_RUST_DRIVER_PCI`, `SAMPLE_RUST_DRIVER_PLATFORM`, `SAMPLE_RUST_DRIVER_USB`, `SAMPLE_RUST_DRIVER_AUXILIARY`, `SAMPLE_RUST_SOC`. Then we have a few DRM-related ones: `DRM_NOVA`, `DRM_TYR`, `NOVA_CORE`. Plus, `PWM_TH1520` and `CPUFREQ_DT_RUST`. Wait, hold on... `DRM_NOVA` depends on `DRM=y`, right? No need to list that dependency, the fuzzer should handle that. In fact, I can just list the key features here: `DRM_NOVA`, `DRM_TYR`, `NOVA_CORE`, `PWM_TH1520`, and `CPUFREQ_DT_RUST`. I trust the fuzzer to enable those if the dependencies are met. That's the cleaner approach. Now, let me broaden the scope a bit. Are there *other* Rust drivers that I should include in this sweep? I see that `rust/kernel/net/phy.rs` was recently modified. Intriguing. Was there a sample PHY driver? The patch modifies the `module_phy_driver!` macro in that file. That's a good lead. Let me check the codebase to see which drivers are actually *using* that `module_phy_driver!` macro. I need to know where this is actually being applied. |
| 56/2 | 2026/06/29 13:16 | tool | grepper |
0mArgs:{
"Expression": "module_phy_driver!",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/phy/ax88796b_rust.rs-12-\ndrivers/net/phy/ax88796b_rust.rs:13:kernel::module_phy_driver! {\ndrivers/net/phy/ax88796b_rust.rs-14- drivers: [PhyAX88772A, PhyAX88772C, PhyAX88796B],\n--\ndrivers/net/phy/qt2025.rs-23-\ndrivers/net/phy/qt2025.rs:24:kernel::module_phy_driver! {\ndrivers/net/phy/qt2025.rs-25- drivers: [PhyQT2025],\n--\nrust/kernel/net/phy.rs=760= const fn as_int(\u0026self) -\u003e u32 {\n--\nrust/kernel/net/phy.rs-782-///\nrust/kernel/net/phy.rs:783:/// kernel::module_phy_driver! {\nrust/kernel/net/phy.rs-784-/// drivers: [PhySample],\n--\nrust/kernel/net/phy.rs=804=macro_rules! module_phy_driver {\n--\nrust/kernel/net/phy.rs-807- (@count_devices $($x:expr),*) =\u003e {\nrust/kernel/net/phy.rs:808: 0usize $(+ $crate::module_phy_driver!(@replace_expr $x 1usize))*\nrust/kernel/net/phy.rs-809- };\n--\nrust/kernel/net/phy.rs=819= struct Module {\n--\nrust/kernel/net/phy.rs-829- static mut DRIVERS: [$crate::net::phy::DriverVTable;\nrust/kernel/net/phy.rs:830: $crate::module_phy_driver!(@count_devices $($driver),+)] =\nrust/kernel/net/phy.rs-831- [$($crate::net::phy::create_phy_driver::\u003c$driver\u003e()),+];\n--\nrust/kernel/net/phy.rs=834= fn init(module: \u0026'static $crate::ThisModule) -\u003e Result\u003cSelf\u003e {\n--\nrust/kernel/net/phy.rs-846-\nrust/kernel/net/phy.rs:847: $crate::module_phy_driver!(@device_table [$($dev),+]);\nrust/kernel/net/phy.rs-848- }\n"
} |
| 57/2 | 2026/06/29 13:16 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 40236 output: 49 thoughts: 37 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Analyzing PHY Driver Configurations** Alright, so the drivers we're dealing with are `AX88796B_RUST_PHY` and `QT2025_PHY`. My first instinct is to dive straight into their configurations. I want to quickly ascertain their key parameters, understand their resource mappings, and check for any potential conflicts or subtle differences in their register settings. This early assessment is crucial. I'm looking for anything that immediately jumps out – specific clock frequencies, interrupt lines, PHY addresses, power-down modes... anything that might impact their integration into the system or suggest potential driver-specific quirks. A quick scan of the defines and any conditional compilation flags will also provide crucial context. I'm mentally comparing them already, looking for overlap or divergences that will guide further investigation. |
| 58/2 | 2026/06/29 13:16 | tool | grepper |
0mArgs:{
"Expression": "config (AX88796B_RUST_PHY|QT2025_PHY)",
"PathPrefix": "drivers/net/phy/"
}Results: {
"Output": "drivers/net/phy/Kconfig=148=config AX88796B_PHY\n--\ndrivers/net/phy/Kconfig-153-\ndrivers/net/phy/Kconfig:154:config AX88796B_RUST_PHY\ndrivers/net/phy/Kconfig-155-\tbool \"Rust reference driver for Asix PHYs\"\n"
} |
| 59/2 | 2026/06/29 13:16 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 40612 output: 33 thoughts: 14 Thoughts: Here's my attempt at summarizing that thought process, tailored for an expert audience: **Analyzing that Config Name** Okay, so I see `QT2025_PHY`. My first thought is: wait a minute, that config name format? That's immediately telling me a few things. The `QT` prefix is probably vendor-specific, which is fine, but it immediately narrows down the playing field. Then I see the numerical portion, `2025`. That's likely a date code, potentially indicating a product generation or revision, probably referencing a specific year. The `PHY` at the end... that screams "Physical Layer" to me, right? So we're talking about a configuration specific to a PHY chip, or a PHY component. I'm already mentally forming an idea of what context this config might be relevant to, and the potential implications of a date-stamped revision. I wonder what the corresponding software version might be? I need to look into this. |
| 60/2 | 2026/06/29 13:16 | tool | grepper |
0mArgs:{
"Expression": "config .*QT2025",
"PathPrefix": "drivers/net/phy/"
}Results: {
"Output": "drivers/net/phy/Kconfig=132=config ADIN1100_PHY\n--\ndrivers/net/phy/Kconfig-138-\ndrivers/net/phy/Kconfig:139:config AMCC_QT2025_PHY\ndrivers/net/phy/Kconfig-140-\ttristate \"AMCC QT2025 PHY\"\n"
} |
| 61/2 | 2026/06/29 13:16 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 40971 output: 26 thoughts: 367 Thoughts: **My Assessment of the Rust Device Driver Abstraction Patch** Okay, so I'm looking at configurations involving `AX88796B_RUST_PHY` and `AMCC_QT2025_PHY`. Let's break down these Rust configurations and the context. My initial thought is that the relevant configs are: `RUST`, `SAMPLES_RUST`, `SAMPLE_RUST_DMA`, `SAMPLE_RUST_DRIVER_I2C`, `SAMPLE_RUST_I2C_CLIENT`, `SAMPLE_RUST_DRIVER_PCI`, `SAMPLE_RUST_DRIVER_PLATFORM`, `SAMPLE_RUST_DRIVER_USB`, `SAMPLE_RUST_DRIVER_AUXILIARY`, `SAMPLE_RUST_SOC`, `DRM_NOVA`, `DRM_TYR`, `NOVA_CORE`, `PWM_TH1520`, `CPUFREQ_DT_RUST`, `AX88796B_RUST_PHY`, and `AMCC_QT2025_PHY`. That looks like a pretty comprehensive set. I see that the patch significantly modifies the core Rust device driver abstractions. This definitely warrants a thorough fuzzing campaign. The rationale for this should be: "The patch modifies core Rust abstractions for device drivers (PCI, USB, Platform, I2C, Auxiliary, ACPI, OF), changing how device ID tables are generated and how match data is retrieved during driver probe. Fuzzing is needed to ensure Rust drivers can still probe successfully and receive correct match data." Given the scope of the modifications, it's clear that this patch is **WorthFuzzing**. The `FocusSymbols` will be empty. The changes appear to be within generic inline functions and macros. Because of the nature of the changes, the fuzzer will naturally hit them as it probes and exercises the enabled Rust drivers. I'll quickly double-check that this covers the extent of Rust drivers to be sure. |
| 62/2 | 2026/06/29 13:16 | tool | grepper |
0mArgs:{
"Expression": "module_.*_driver!",
"PathPrefix": ""
}Results: {
"Output": "drivers/cpufreq/rcpufreq_dt.rs=206= fn probe\u003c'bound\u003e(\n--\ndrivers/cpufreq/rcpufreq_dt.rs-214-\ndrivers/cpufreq/rcpufreq_dt.rs:215:module_platform_driver! {\ndrivers/cpufreq/rcpufreq_dt.rs-216- type: CPUFreqDTDriver,\n--\ndrivers/gpu/drm/nova/nova.rs-10-\ndrivers/gpu/drm/nova/nova.rs:11:kernel::module_auxiliary_driver! {\ndrivers/gpu/drm/nova/nova.rs-12- type: NovaDriver,\n--\ndrivers/gpu/drm/tyr/tyr.rs-15-\ndrivers/gpu/drm/tyr/tyr.rs:16:kernel::module_platform_driver! {\ndrivers/gpu/drm/tyr/tyr.rs-17- type: TyrPlatformDriver,\n--\ndrivers/net/phy/ax88796b_rust.rs-12-\ndrivers/net/phy/ax88796b_rust.rs:13:kernel::module_phy_driver! {\ndrivers/net/phy/ax88796b_rust.rs-14- drivers: [PhyAX88772A, PhyAX88772C, PhyAX88796B],\n--\ndrivers/net/phy/qt2025.rs-23-\ndrivers/net/phy/qt2025.rs:24:kernel::module_phy_driver! {\ndrivers/net/phy/qt2025.rs-25- drivers: [PhyQT2025],\n--\ndrivers/pwm/pwm_th1520.rs=315= fn probe\u003c'bound\u003e(\n--\ndrivers/pwm/pwm_th1520.rs-358-\ndrivers/pwm/pwm_th1520.rs:359:kernel::module_pwm_platform_driver! {\ndrivers/pwm/pwm_th1520.rs-360- type: Th1520PwmPlatformDriver,\n--\nrust/kernel/driver.rs-86-//!\nrust/kernel/driver.rs:87://! Typically, bus abstractions want to provide a bus specific `module_bus_driver!` macro, which\nrust/kernel/driver.rs-88-//! creates a kernel module with exactly one [`Registration`] for the bus specific adapter.\n--\nrust/kernel/i2c.rs=225= fn acpi_id_table() -\u003e Option\u003cacpi::IdTable\u003cSelf::IdInfo\u003e\u003e {\n--\nrust/kernel/i2c.rs-234-/// ```ignore\nrust/kernel/i2c.rs:235:/// kernel::module_i2c_driver! {\nrust/kernel/i2c.rs-236-/// type: MyDriver,\n--\nrust/kernel/net/phy.rs=760= const fn as_int(\u0026self) -\u003e u32 {\n--\nrust/kernel/net/phy.rs-782-///\nrust/kernel/net/phy.rs:783:/// kernel::module_phy_driver! {\nrust/kernel/net/phy.rs-784-/// drivers: [PhySample],\n--\nrust/kernel/net/phy.rs=804=macro_rules! module_phy_driver {\n--\nrust/kernel/net/phy.rs-807- (@count_devices $($x:expr),*) =\u003e {\nrust/kernel/net/phy.rs:808: 0usize $(+ $crate::module_phy_driver!(@replace_expr $x 1usize))*\nrust/kernel/net/phy.rs-809- };\n--\nrust/kernel/net/phy.rs=819= struct Module {\n--\nrust/kernel/net/phy.rs-829- static mut DRIVERS: [$crate::net::phy::DriverVTable;\nrust/kernel/net/phy.rs:830: $crate::module_phy_driver!(@count_devices $($driver),+)] =\nrust/kernel/net/phy.rs-831- [$($crate::net::phy::create_phy_driver::\u003c$driver\u003e()),+];\n--\nrust/kernel/net/phy.rs=834= fn init(module: \u0026'static $crate::ThisModule) -\u003e Result\u003cSelf\u003e {\n--\nrust/kernel/net/phy.rs-846-\nrust/kernel/net/phy.rs:847: $crate::module_phy_driver!(@device_table [$($dev),+]);\nrust/kernel/net/phy.rs-848- }\n--\nrust/kernel/pci.rs=127= extern \"C\" fn remove_callback(pdev: *mut bindings::pci_dev) {\n--\nrust/kernel/pci.rs-147-///```ignore\nrust/kernel/pci.rs:148:/// kernel::module_pci_driver! {\nrust/kernel/pci.rs-149-/// type: MyDriver,\n--\nrust/kernel/platform.rs=137= fn acpi_id_table() -\u003e Option\u003cacpi::IdTable\u003cSelf::IdInfo\u003e\u003e {\n--\nrust/kernel/platform.rs-146-/// ```ignore\nrust/kernel/platform.rs:147:/// kernel::module_platform_driver! {\nrust/kernel/platform.rs-148-/// type: MyDriver,\n--\nrust/kernel/pwm.rs=710= fn drop(\u0026mut self) {\n--\nrust/kernel/pwm.rs-724-///```ignore\nrust/kernel/pwm.rs:725:/// kernel::module_pwm_platform_driver! {\nrust/kernel/pwm.rs-726-/// type: MyDriver,\n--\nrust/kernel/pwm.rs=734=macro_rules! module_pwm_platform_driver {\nrust/kernel/pwm.rs-735- ($($user_args:tt)*) =\u003e {\nrust/kernel/pwm.rs:736: $crate::module_platform_driver! {\nrust/kernel/pwm.rs-737- $($user_args)*\n--\nrust/kernel/usb.rs=472=unsafe impl Sync for Device\u003cdevice::Bound\u003e {}\n--\nrust/kernel/usb.rs-478-/// ```ignore\nrust/kernel/usb.rs:479:/// module_usb_driver! {\nrust/kernel/usb.rs-480-/// type: MyDriver,\n--\nrust/macros/module.rs=428=pub(crate) fn module(info: ModuleInfo) -\u003e Result\u003cTokenStream\u003e {\n--\nrust/macros/module.rs-516- /// The `LocalModule` type is the type of the module created by `module!`,\nrust/macros/module.rs:517: /// `module_pci_driver!`, `module_platform_driver!`, etc.\nrust/macros/module.rs-518- type LocalModule = #type_;\n--\nsamples/rust/rust_debugfs.rs-57-\nsamples/rust/rust_debugfs.rs:58:kernel::module_platform_driver! {\nsamples/rust/rust_debugfs.rs-59- type: RustDebugFs,\n--\nsamples/rust/rust_dma.rs=110= fn drop(self: Pin\u003c\u0026mut Self\u003e) {\n--\nsamples/rust/rust_dma.rs-125-\nsamples/rust/rust_dma.rs:126:kernel::module_pci_driver! {\nsamples/rust/rust_dma.rs-127- type: DmaSampleDriver,\n--\nsamples/rust/rust_driver_i2c.rs=60= fn unbind\u003c'bound\u003e(idev: \u0026'bound i2c::I2cClient\u003cCore\u003c'_\u003e\u003e, _this: Pin\u003c\u0026Self\u003e) {\n--\nsamples/rust/rust_driver_i2c.rs-64-\nsamples/rust/rust_driver_i2c.rs:65:kernel::module_i2c_driver! {\nsamples/rust/rust_driver_i2c.rs-66- type: SampleDriver,\n--\nsamples/rust/rust_driver_pci.rs=182= fn drop(\u0026mut self) {\n--\nsamples/rust/rust_driver_pci.rs-186-\nsamples/rust/rust_driver_pci.rs:187:kernel::module_pci_driver! {\nsamples/rust/rust_driver_pci.rs-188- type: SampleDriver,\n--\nsamples/rust/rust_driver_platform.rs=181= fn drop(\u0026mut self) {\n--\nsamples/rust/rust_driver_platform.rs-185-\nsamples/rust/rust_driver_platform.rs:186:kernel::module_platform_driver! {\nsamples/rust/rust_driver_platform.rs-187- type: SampleDriver,\n--\nsamples/rust/rust_driver_usb.rs=42= fn disconnect\u003c'bound\u003e(intf: \u0026'bound usb::Interface\u003cCore\u003c'_\u003e\u003e, _data: Pin\u003c\u0026Self\u003e) {\n--\nsamples/rust/rust_driver_usb.rs-47-\nsamples/rust/rust_driver_usb.rs:48:kernel::module_usb_driver! {\nsamples/rust/rust_driver_usb.rs-49- type: SampleDriver,\n--\nsamples/rust/rust_i2c_client.rs=131= fn unbind\u003c'bound\u003e(\n--\nsamples/rust/rust_i2c_client.rs-141-\nsamples/rust/rust_i2c_client.rs:142:kernel::module_platform_driver! {\nsamples/rust/rust_i2c_client.rs-143- type: SampleDriver,\n--\nsamples/rust/rust_soc.rs=42= fn probe\u003c'bound\u003e(\n--\nsamples/rust/rust_soc.rs-71-\nsamples/rust/rust_soc.rs:72:kernel::module_platform_driver! {\nsamples/rust/rust_soc.rs-73- type: SampleSocDriver,\n"
} |
| 63/2 | 2026/06/29 13:16 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 44333 output: 268 thoughts: 262 Thoughts: **My Analysis of the Fuzzing Configuration** Alright, I've got the complete configuration in front of me. Now, let's break down what we're looking at and determine the appropriate approach. First, the `WorthFuzzing` flag is set to `true`, which is what I'd expect. The `FocusSymbols` array is empty, implying a broad scope, which makes sense given the nature of the change. The meat of this lies within the `EnableConfigs` list. It’s extensive and targets several key Rust drivers and related modules. We have "RUST", and "SAMPLES_RUST" which are foundational. Then, we have specific drivers: "SAMPLE_RUST_DMA", "SAMPLE_RUST_DRIVER_I2C", "SAMPLE_RUST_I2C_CLIENT", "SAMPLE_RUST_DRIVER_PCI", "SAMPLE_RUST_DRIVER_PLATFORM", "SAMPLE_RUST_DRIVER_USB", "SAMPLE_RUST_DRIVER_AUXILIARY", and "SAMPLE_RUST_SOC". Furthermore, there are some DRM (Direct Rendering Manager) configurations like "DRM_NOVA" and "DRM_TYR", and platform specific ones like "NOVA_CORE", "PWM_TH1520", "CPUFREQ_DT_RUST", "AX88796B_RUST_PHY", and "AMCC_QT2025_PHY". This encompasses a significant portion of the driver ecosystem. The core reasoning highlights the critical modification: the patch is fundamentally altering Rust's core abstractions for device drivers. It's affecting how device ID tables are created and how match data is accessed during driver probing. This is a crucial area. If those changes introduce unexpected behavior during driver probing, the device will be completely inaccessible. This necessitates fuzzing, and it's being correctly applied here, to ensure all the Rust drivers can probe accurately and correctly receive all the match data they need to function. It makes perfect sense to focus on this area. We need to ensure that the driver ecosystem remains robust after this update. |
| 64/2 | 2026/06/29 13:16 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"RUST",
"SAMPLES_RUST",
"SAMPLE_RUST_DMA",
"SAMPLE_RUST_DRIVER_I2C",
"SAMPLE_RUST_I2C_CLIENT",
"SAMPLE_RUST_DRIVER_PCI",
"SAMPLE_RUST_DRIVER_PLATFORM",
"SAMPLE_RUST_DRIVER_USB",
"SAMPLE_RUST_DRIVER_AUXILIARY",
"SAMPLE_RUST_SOC",
"DRM_NOVA",
"DRM_TYR",
"NOVA_CORE",
"PWM_TH1520",
"CPUFREQ_DT_RUST",
"AX88796B_RUST_PHY",
"AMCC_QT2025_PHY"
],
"FocusSymbols": [],
"Reasoning": "The patch modifies core Rust abstractions for device drivers (PCI, USB, Platform, I2C, Auxiliary, ACPI, OF), changing how device ID tables are generated and how match data is retrieved during driver probe. Fuzzing is needed to ensure Rust drivers can still probe successfully and receive correct match data.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"RUST",
"SAMPLES_RUST",
"SAMPLE_RUST_DMA",
"SAMPLE_RUST_DRIVER_I2C",
"SAMPLE_RUST_I2C_CLIENT",
"SAMPLE_RUST_DRIVER_PCI",
"SAMPLE_RUST_DRIVER_PLATFORM",
"SAMPLE_RUST_DRIVER_USB",
"SAMPLE_RUST_DRIVER_AUXILIARY",
"SAMPLE_RUST_SOC",
"DRM_NOVA",
"DRM_TYR",
"NOVA_CORE",
"PWM_TH1520",
"CPUFREQ_DT_RUST",
"AX88796B_RUST_PHY",
"AMCC_QT2025_PHY"
],
"FocusSymbols": [],
"Reasoning": "The patch modifies core Rust abstractions for device drivers (PCI, USB, Platform, I2C, Auxiliary, ACPI, OF), changing how device ID tables are generated and how match data is retrieved during driver probe. Fuzzing is needed to ensure Rust drivers can still probe successfully and receive correct match data.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|