rust: watchdog: add watchdog device abstraction
Subsystems (2)
PATCH 1/2 rust: watchdog: add watchdog device abstraction
Add Rust abstractions for the Linux watchdog subsystem, enabling watchdog drivers to be written in Rust.
The abstraction follows the pattern established by the PHY driver abstraction (rust/kernel/net/phy.rs):
- A Device wrapper around struct watchdog_device providing safe accessors for timeout, pretimeout, and status fields.
- A #[vtable] WatchdogOps trait where start() is mandatory and stop(), ping(), set_timeout(), set_pretimeout(), and get_timeleft() are optional.
- An Adapter struct with unsafe extern "C" fn callbacks that bridge the C watchdog core to Rust trait methods.
- A create_watchdog_ops() const function that populates the C watchdog_ops struct at compile time.
- A Registration type that heap-allocates the watchdog_device via KBox to ensure pointer stability (the C core stores back-pointers into the device struct), and wraps watchdog_register_device / watchdog_unregister_device with RAII semantics.
The Registration::register method takes a &'static ThisModule parameter to set the owner field in watchdog_ops, ensuring correct module reference counting when userspace opens /dev/watchdog.
Also add C helper functions for inline watchdog functions that bindgen cannot handle and include linux/watchdog.h in the bindings header.
--- rust/bindings/bindings_helper.h | 1 + rust/helpers/helpers.c | 1 + rust/helpers/watchdog.c | 38 ++++ rust/kernel/lib.rs | 2 + rust/kernel/watchdog.rs | 348 ++++++++++++++++++++++++++++++++ 5 files changed, 390 insertions(+) create mode 100644 rust/helpers/watchdog.c create mode 100644 rust/kernel/watchdog.rs
rust/bindings/bindings_helper.h +1 -0
@@ -84,6 +84,7 @@#include <linux/tracepoint.h> #include <linux/usb.h> #include <linux/wait.h> +#include <linux/watchdog.h> #include <linux/workqueue.h> #include <linux/xarray.h> #include <trace/events/rust_sample.h>
rust/helpers/helpers.c +1 -0
@@ -60,5 +60,6 @@#include "usb.c" #include "vmalloc.c" #include "wait.c" +#include "watchdog.c" #include "workqueue.c" #include "xarray.c"
rust/helpers/watchdog.c new file +38 -0
@@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/watchdog.h> + +bool rust_helper_watchdog_active (struct watchdog_device *wdd) +{ +return watchdog_active (wdd); +} + +bool rust_helper_watchdog_hw_running (struct watchdog_device *wdd) +{ +return watchdog_hw_running (wdd); +} + +void rust_helper_watchdog_set_nowayout (struct watchdog_device *wdd,bool nowayout) +{ +watchdog_set_nowayout (wdd, nowayout); +} + +void rust_helper_watchdog_stop_on_reboot (struct watchdog_device *wdd) +{ +watchdog_stop_on_reboot (wdd); +} + +void rust_helper_watchdog_stop_on_unregister (struct watchdog_device *wdd) +{ +watchdog_stop_on_unregister (wdd); +} + +void rust_helper_watchdog_set_drvdata (struct watchdog_device *wdd,void *data) +{ +watchdog_set_drvdata (wdd, data); +} + +void *rust_helper_watchdog_get_drvdata (struct watchdog_device *wdd) +{ +return watchdog_get_drvdata (wdd); +}
rust/kernel/lib.rs +2 -0
@@ -149,6 +149,8 @@pub mod transmute;pub mod types;pub mod uaccess; +#[cfg( CONFIG_WATCHDOG )] +pub mod watchdog;#[cfg( CONFIG_USB = "y" )] pub mod usb;pub mod workqueue;
rust/kernel/watchdog.rs new file +348 -0
348 lines not on this page · raw message
Signature · 1 line
2.43.0
PATCH 2/2 watchdog: softdog_rs: add Rust software watchdog driver
Add a Rust software watchdog driver that uses the new Rust watchdog abstraction. This demonstrates that the abstraction is functional and can be used to write real watchdog drivers.
The driver implements start and stop operations. Unlike the C softdog, this simplified version does not use hrtimers for the actual countdown -- the watchdog core handles the timeout expiry and keepalive management. This makes it suitable as a proof-of-concept driver for the Rust watchdog abstraction.
The driver registers as "Rust Software Watchdog" with a default timeout of 60 seconds, matching the C softdog's defaults.
The Kconfig option SOFT_WATCHDOG_RS depends on !SOFT_WATCHDOG to prevent both drivers from being enabled simultaneously.
--- drivers/watchdog/Kconfig | 12 +++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/softdog_rs.rs | 88 ++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 drivers/watchdog/softdog_rs.rs
drivers/watchdog/Kconfig +12 -0
@@ -160,6 +160,18 @@ config SOFT_WATCHDOG To compile this driver as a module, choose M here: the module will be called softdog. +config SOFT_WATCHDOG_RS + tristate "Rust software watchdog" + depends on RUST && !SOFT_WATCHDOG + select WATCHDOG_CORE + help + A software watchdog driver written in Rust using the Rust watchdog + device abstraction. This is a simplified Rust equivalent of the + C softdog driver. + + To compile this driver as a module, choose M here: the + module will be called softdog_rs. + config SOFT_WATCHDOG_PRETIMEOUT bool "Software watchdog pretimeout governor support" depends on SOFT_WATCHDOG && WATCHDOG_PRETIMEOUT_GOV
drivers/watchdog/Makefile +1 -0
@@ -239,6 +239,7 @@ obj-$(CONFIG_MAX77620_WATCHDOG) += max77620_wdt.o obj-$(CONFIG_NCT6694_WATCHDOG) += nct6694_wdt.o obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o +obj-$(CONFIG_SOFT_WATCHDOG_RS) += softdog_rs.o obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
drivers/watchdog/softdog_rs.rs new file +88 -0
88 lines not on this page · raw message
Signature · 1 line
2.43.0
kernel test robot
build botRe: [PATCH 2/2] watchdog: softdog_rs: add Rust software watchdog driver
kernel test robot noticed the following build errors:
Hi Artem,
kernel test robot noticed the following build errors:
[auto build test ERROR on rust/rust-next]
[also build test ERROR on linus/master v7.0-rc5 next-20260323] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Artem-Lytkin/watchdog-softdog_rs-add-Rust-software-watchdog-driver/20260324-145829 base: https://github.com/Rust-for-Linux/linux rust-next patch link: https://lore.kernel.org/r/20260323195209.5581-2-iprintercanon%40gmail.com patch subject: [PATCH 2/2] watchdog: softdog_rs: add Rust software watchdog driver config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20260324/[email protected]/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) rustc: rustc 1.88.0 (6b00bc388 2025-06-23) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260324/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
PATH=/opt/cross/clang-20/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
INFO PATH=/opt/cross/rustc-1.88.0-bindgen-0.72.1/cargo/bin:/opt/cross/clang-20/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/usr/bin/timeout -k 100 12h /usr/bin/make KCFLAGS=\ -fno-crash-diagnostics\ -Wno-error=return-type\ -Wreturn-type\ -funsigned-char\ -Wundef\ -falign-functions=64 W=1 --keep-going LLVM=1 -j32 -C source O=/kbuild/obj/consumer/x86_64-rhel-9.4-rust ARCH=x86_64 SHELL=/bin/bash rustfmtcheck
make: Entering directory '/kbuild/src/consumer'
make[1]: Entering directory '/kbuild/obj/consumer/x86_64-rhel-9.4-rust'
>> Diff in drivers/watchdog/softdog_rs.rs:51:
},
}; -static mut SOFTDOG_OPS: bindings::watchdog_ops =
- watchdog::create_watchdog_ops::<SoftdogOps>();
+static mut SOFTDOG_OPS: bindings::watchdog_ops = watchdog::create_watchdog_ops::<SoftdogOps>();
struct SoftdogModule {
_reg: watchdog::Registration,
Diff in rust/kernel/watchdog.rs:94:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn start_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn start_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/watchdog.rs:108:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn stop_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn stop_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/watchdog.rs:122:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn ping_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn ping_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/lib.rs:155:
pub mod transmute;
pub mod types;
pub mod uaccess;
-#[cfg(CONFIG_WATCHDOG)]
-pub mod watchdog;
#[cfg(CONFIG_USB = "y")]
pub mod usb;
+#[cfg(CONFIG_WATCHDOG)]
+pub mod watchdog;
pub mod workqueue;
pub mod xarray; Diff in rust/kernel/watchdog.rs:94:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn start_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn start_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/watchdog.rs:108:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn stop_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn stop_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/watchdog.rs:122:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn ping_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn ping_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) }; make[2]: *** [Makefile:1912: rustfmt] Error 123
make[2]: Target 'rustfmtcheck' not remade because of errors. make[1]: Leaving directory '/kbuild/obj/consumer/x86_64-rhel-9.4-rust' make[1]: *** [Makefile:248: __sub-make] Error 2
make[1]: Target 'rustfmtcheck' not remade because of errors.
make: *** [Makefile:248: __sub-make] Error 2
make: Target 'rustfmtcheck' not remade because of errors.
make: Leaving directory '/kbuild/src/consumer'
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
kernel test robot
build botkernel test robot noticed the following build errors:
Hi Artem,
kernel test robot noticed the following build errors:
[auto build test ERROR on rust/rust-next]
[also build test ERROR on linus/master v7.0-rc5 next-20260323] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Artem-Lytkin/watchdog-softdog_rs-add-Rust-software-watchdog-driver/20260324-145829 base: https://github.com/Rust-for-Linux/linux rust-next patch link: https://lore.kernel.org/r/20260323195209.5581-1-iprintercanon%40gmail.com patch subject: [PATCH 1/2] rust: watchdog: add watchdog device abstraction config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20260324/[email protected]/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) rustc: rustc 1.88.0 (6b00bc388 2025-06-23) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260324/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All error/warnings (new ones prefixed by >>):
PATH=/opt/cross/clang-20/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
INFO PATH=/opt/cross/rustc-1.88.0-bindgen-0.72.1/cargo/bin:/opt/cross/clang-20/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/usr/bin/timeout -k 100 12h /usr/bin/make KCFLAGS=\ -fno-crash-diagnostics\ -Wno-error=return-type\ -Wreturn-type\ -funsigned-char\ -Wundef\ -falign-functions=64 W=1 --keep-going LLVM=1 -j32 -C source O=/kbuild/obj/consumer/x86_64-rhel-9.4-rust ARCH=x86_64 SHELL=/bin/bash rustfmtcheck
make: Entering directory '/kbuild/src/consumer'
make[1]: Entering directory '/kbuild/obj/consumer/x86_64-rhel-9.4-rust'
>> Diff in rust/kernel/watchdog.rs:94:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn start_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn start_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/watchdog.rs:108:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn stop_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn stop_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/watchdog.rs:122:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn ping_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn ping_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/lib.rs:155:
pub mod transmute;
pub mod types;
pub mod uaccess;
-#[cfg(CONFIG_WATCHDOG)]
-pub mod watchdog;
#[cfg(CONFIG_USB = "y")]
pub mod usb;
+#[cfg(CONFIG_WATCHDOG)]
+pub mod watchdog;
pub mod workqueue;
pub mod xarray;>> Diff in rust/kernel/watchdog.rs:94:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn start_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn start_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/watchdog.rs:108:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn stop_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn stop_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) };
Diff in rust/kernel/watchdog.rs:122:
/// # Safety
///
/// `wdd` must be passed by the corresponding callback in `watchdog_ops`.
- unsafe extern "C" fn ping_callback(
- wdd: *mut bindings::watchdog_device,
- ) -> core::ffi::c_int {
+ unsafe extern "C" fn ping_callback(wdd: *mut bindings::watchdog_device) -> core::ffi::c_int {
from_result(|| {
// SAFETY: The watchdog core serialises access to the device.
let dev = unsafe { Device::from_raw(wdd) }; make[2]: *** [Makefile:1912: rustfmt] Error 123
make[1]: Leaving directory '/kbuild/obj/consumer/x86_64-rhel-9.4-rust' make[1]: *** [Makefile:248: __sub-make] Error 2
make: *** [Makefile:248: __sub-make] Error 2
make[1]: Target 'rustfmtcheck' not remade because of errors.
make: Target 'rustfmtcheck' not remade because of errors.
make: Leaving directory '/kbuild/src/consumer'
make[2]: Target 'rustfmtcheck' not remade because of errors.
--
>> warning: this function has too many arguments (8/7)
--> rust/kernel/watchdog.rs:290:5
|
290 | / pub fn register(
291 | | module: &'static crate::ThisModule,
292 | | parent: Option<&device::Device>,
293 | | info: &'static bindings::watchdog_info,
... |
298 | | nowayout: bool,
299 | | ) -> Result<Self> {
| |_____________________^
| = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments
= note: -W clippy::too-many-arguments implied by -W clippy::all
= help: to override -W clippy::all add #[allow(clippy::too_many_arguments)]
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki