OpenSBI Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] RISC-V SBI watchdog support
@ 2026-10-02  8:30 Prajwal N
  2026-10-02  8:30 ` [PATCH 1/4] lib: sbi: Add timer tick to time conversion helper Prajwal N
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Prajwal N @ 2026-10-02  8:30 UTC (permalink / raw)
  To: anup; +Cc: opensbi, prajwal.n.oss, Prajwal N

This series introduces support for the RISC-V SBI watchdog extension,
which provides the watchdog functionality for the Supervisor software.

The SBI watchdog extension exposes watchdog functionality including
start, stop, pat, read and write attributes to the S-mode software via
SBI calls. The extension manages the watchdog timer in M-mode using the
system timer.

The S-mode software can also optionally subscribe for
watchdog pretimeout notification which is delivered as a Message
Signaled Interrupt (MSI) before the current watch period expires.
On watchdog expiry, a platform system reset is triggered.

The series consists of the following changes:

- Patch 1 adds helper function to convert timer tick delta to a
  specified time unit and a wrapper to convert the time tick to
  microsecond.

- Patch 2 adds the SBI watchdog extension ID and function IDs
  for supported operations, including start, stop, pat, and
  atrribute read and write.

- Patch 3 implements the SBI watchdog functionality including
  start, stop, pat, read and write attributes, pretimeout and
  timeout handlers.

- Patch 4 implements ecall handler functionality to delegate
  the ecall to SBI watchdog framework

Prajwal N (4):
  lib: sbi: Add timer tick to time conversion helper
  include: sbi: Add SBI watchdog extension definitions
  lib: sbi: Add SBI watchdog framework
  lib: sbi: Add ecall handler for SBI watchdog

 include/sbi/sbi_ecall_interface.h |  33 +++
 include/sbi/sbi_timer.h           |  12 +
 include/sbi/sbi_wdt.h             |  72 +++++
 lib/sbi/Kconfig                   |   4 +
 lib/sbi/objects.mk                |   4 +
 lib/sbi/sbi_ecall_wdt.c           |  79 ++++++
 lib/sbi/sbi_init.c                |   8 +
 lib/sbi/sbi_timer.c               |   5 +
 lib/sbi/sbi_wdt.c                 | 455 ++++++++++++++++++++++++++++++
 9 files changed, 672 insertions(+)
 create mode 100644 include/sbi/sbi_wdt.h
 create mode 100644 lib/sbi/sbi_ecall_wdt.c
 create mode 100644 lib/sbi/sbi_wdt.c

-- 
2.43.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] lib: sbi: Add timer tick to time conversion helper
  2026-10-02  8:30 [PATCH 0/4] RISC-V SBI watchdog support Prajwal N
@ 2026-10-02  8:30 ` Prajwal N
  2026-10-02  8:30 ` [PATCH 2/4] include: sbi: Add SBI watchdog extension definitions Prajwal N
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Prajwal N @ 2026-10-02  8:30 UTC (permalink / raw)
  To: anup; +Cc: opensbi, prajwal.n.oss, Prajwal N

Add helper function to convert timer tick delta to a specified time
unit using the corresponding unit frequency.
Add a wrapper to convert the timer ticks to microsecond.

The generic helper allows the SBI watchdog and other timer users to
share the same conversion logic and can be extended to support
additional time units.

Signed-off-by: Prajwal N <prajwal.n@oss.qualcomm.com>
---
 include/sbi/sbi_timer.h | 12 ++++++++++++
 lib/sbi/sbi_timer.c     |  5 +++++
 2 files changed, 17 insertions(+)

diff --git a/include/sbi/sbi_timer.h b/include/sbi/sbi_timer.h
index 17d6c1dc..3e1243b2 100644
--- a/include/sbi/sbi_timer.h
+++ b/include/sbi/sbi_timer.h
@@ -12,6 +12,9 @@
 
 #include <sbi/sbi_list.h>
 
+/** Macro for seconds to microseconds conversion */
+#define SEC_TO_MICROSEC		1000000ULL
+
 /** Timer event re-start details */
 struct sbi_timer_event_restart {
 	/** Flag indicating whether event re-start is required */
@@ -88,6 +91,15 @@ struct sbi_timer_device {
 
 struct sbi_scratch;
 
+/** Compute timer value in given unit sec from timer tick delta */
+u64 sbi_timer_convert_ticks(ulong from_ticks, u64 unit_freq);
+
+/** Compute microseconds from timer tick delta */
+static inline u64 sbi_timer_ticks_to_usec(ulong ticks)
+{
+	return sbi_timer_convert_ticks(ticks, SEC_TO_MICROSEC);
+}
+
 /** Compute timer value delta based on arbitary units */
 u64 sbi_timer_compute_delta(ulong units, u64 unit_freq);
 
diff --git a/lib/sbi/sbi_timer.c b/lib/sbi/sbi_timer.c
index 78aaa32e..aeb860eb 100644
--- a/lib/sbi/sbi_timer.c
+++ b/lib/sbi/sbi_timer.c
@@ -58,6 +58,11 @@ static void nop_delay_fn(void *opaque)
 	cpu_relax();
 }
 
+u64 sbi_timer_convert_ticks(ulong from_ticks, u64 unit_freq)
+{
+	return (from_ticks * unit_freq) / ((u64)timer_dev->timer_freq);
+}
+
 u64 sbi_timer_compute_delta(ulong units, u64 unit_freq)
 {
 	u64 delta;
-- 
2.43.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/4] include: sbi: Add SBI watchdog extension definitions
  2026-10-02  8:30 [PATCH 0/4] RISC-V SBI watchdog support Prajwal N
  2026-10-02  8:30 ` [PATCH 1/4] lib: sbi: Add timer tick to time conversion helper Prajwal N
@ 2026-10-02  8:30 ` Prajwal N
  2026-10-02  8:30 ` [PATCH 3/4] lib: sbi: Add SBI watchdog framework Prajwal N
  2026-10-02  8:30 ` [PATCH 4/4] lib: sbi: Add ecall handler for SBI watchdog Prajwal N
  3 siblings, 0 replies; 8+ messages in thread
From: Prajwal N @ 2026-10-02  8:30 UTC (permalink / raw)
  To: anup; +Cc: opensbi, prajwal.n.oss, Prajwal N

Add the SBI watchdog extension ID and function IDs
for supported operations, including start, stop, pat,
and attribute read and write.

Define the attribute IDs exposed by the SBI watchdog
extension, including watchdog capabilities such as
MSI support and configurable watchdog parameters.

Signed-off-by: Prajwal N <prajwal.n@oss.qualcomm.com>
---
 include/sbi/sbi_ecall_interface.h | 33 +++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index fd4e77ca..338395fb 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -38,6 +38,7 @@
 #define SBI_EXT_SSE				0x535345
 #define SBI_EXT_FWFT				0x46574654
 #define SBI_EXT_MPXY				0x4D505859
+#define SBI_EXT_WDT				0x574454
 
 /* SBI function IDs for BASE extension*/
 #define SBI_EXT_BASE_GET_SPEC_VERSION		0x0
@@ -492,6 +493,38 @@ enum sbi_sse_state {
 #define SBI_MPXY_NOTIF_HDR_LOST_OFFSET		0x08
 #define SBI_MPXY_NOTIF_HDR_RESERVED_OFFSET	0x0C
 
+/* SBI function IDs for WDT extension */
+#define SBI_EXT_WATCHDOG_READ_ATTRIBUTE			0x0
+#define SBI_EXT_WATCHDOG_WRITE_ATTRIBUTE		0x1
+#define SBI_EXT_WATCHDOG_WRITE_NOTIF_MSI_MESSAGE	0x2
+#define SBI_EXT_WATCHDOG_START				0x3
+#define SBI_EXT_WATCHDOG_STOP				0x4
+#define SBI_EXT_WATCHDOG_PAT				0x5
+
+/* SBI WDT Attributes. */
+enum sbi_wdt_attr_id {
+	/* MSI and SSE capability flags */
+	SBI_WDT_CAPABILITY		= 0x00000000,
+	/* Watchdog state */
+	SBI_WDT_STATE			= 0x00000001,
+	/* Minimum watchdog timeout supported in us */
+	SBI_WDT_MIN_PERIOD		= 0x00000002,
+	/* Watchdog timeout period in us */
+	SBI_WDT_PERIOD			= 0x00000003,
+	/* Time left until watchdog expiry in us */
+	SBI_WDT_TIME_LEFT		= 0x00000004,
+	/* Watchdog pretimeout in us */
+	SBI_WDT_NOTIF_TIME		= 0x00000005,
+	/* MSI target address low 32-bit */
+	SBI_WDT_NOTIF_MSI_ADDR_LOW	= 0x00000006,
+	/* MSI target address high 32-bit */
+	SBI_WDT_NOTIF_MSI_ADDR_HIGH	= 0x00000007,
+	/* MSI data */
+	SBI_WDT_NOTIF_MSI_DATA		= 0x00000008,
+	SBI_WDT_ATTR_MAX		= 0x00000009,
+	SBI_WDT_ATTR_RESERVED_MAX	= 0xFFFFFFFF
+};
+
 /* SBI base specification related macros */
 #define SBI_SPEC_VERSION_MAJOR_OFFSET		24
 #define SBI_SPEC_VERSION_MAJOR_MASK		0x7f
-- 
2.43.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/4] lib: sbi: Add SBI watchdog framework
  2026-10-02  8:30 [PATCH 0/4] RISC-V SBI watchdog support Prajwal N
  2026-10-02  8:30 ` [PATCH 1/4] lib: sbi: Add timer tick to time conversion helper Prajwal N
  2026-10-02  8:30 ` [PATCH 2/4] include: sbi: Add SBI watchdog extension definitions Prajwal N
@ 2026-10-02  8:30 ` Prajwal N
  2026-10-05  3:33   ` Rahul Pathak
                     ` (2 more replies)
  2026-10-02  8:30 ` [PATCH 4/4] lib: sbi: Add ecall handler for SBI watchdog Prajwal N
  3 siblings, 3 replies; 8+ messages in thread
From: Prajwal N @ 2026-10-02  8:30 UTC (permalink / raw)
  To: anup; +Cc: opensbi, prajwal.n.oss, Prajwal N

Update the build infrastructure to include the SBI
watchdog compilation.

Implement the SBI watchdog functionality including
start, stop, pat, read and write attributes,
pretimeout and timeout handlers.

Signed-off-by: Prajwal N <prajwal.n@oss.qualcomm.com>
---
 include/sbi/sbi_wdt.h |  72 +++++++
 lib/sbi/objects.mk    |   1 +
 lib/sbi/sbi_init.c    |   8 +
 lib/sbi/sbi_wdt.c     | 455 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 536 insertions(+)
 create mode 100644 include/sbi/sbi_wdt.h
 create mode 100644 lib/sbi/sbi_wdt.c

diff --git a/include/sbi/sbi_wdt.h b/include/sbi/sbi_wdt.h
new file mode 100644
index 00000000..43f866dc
--- /dev/null
+++ b/include/sbi/sbi_wdt.h
@@ -0,0 +1,72 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Qualcomm Inc.
+ *
+ * Authors:
+ *   Prajwal N <prajwal.n@oss.qualcomm.com>
+ */
+
+#ifndef __SBI_WDT_H__
+#define __SBI_WDT_H__
+
+/**
+ * Read the watchdog attribute
+ * @param attribute_id The wdt attribute id to be read
+ * @param attribute_value The value of attribute returned
+ * @return int error
+ */
+int sbi_watchdog_read_attribute(u32 attribute_id, u32* attribute_value);
+
+/**
+ * Write the watchdog attribute
+ * @param attribute_id The wdt attribute id to be written
+ * @param attribute_value The wdt attribute value to be written
+ * @return int error
+ */
+int sbi_watchdog_write_attribute(u32 attribute_id, u32 attribute_value);
+
+/**
+ * Write the watchdog MSI message attribute
+ * @param msi_addr_low The value of MSI low address
+ * @param msi_addr_high The value of MSI high address
+ * @param msi_data The value of MSI data
+ * @return int error
+ */
+int sbi_watchdog_write_notif_msi_message(u32 msi_addr_low, u32 msi_addr_high, u32 msi_data);
+
+/**
+ * Start the watchdog
+ * @param void
+ * @return int error
+ */
+int sbi_watchdog_start(void);
+
+/**
+ * Stop the watchdog
+ * @param void
+ * @return int error
+ */
+int sbi_watchdog_stop(void);
+
+/**
+ * Pat the watchdog
+ * @param void
+ * @return int error
+ */
+int sbi_watchdog_pat(void);
+
+/**
+ * Initialize the watchdog
+ * @param void
+ * @return int error
+ */
+int sbi_watchdog_init(void);
+
+/**
+ * Remove the watchdog
+ * @param void
+ * @return int error
+ */
+int sbi_watchdog_exit(void);
+#endif
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index ae27d0c5..c8bdc94a 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -106,5 +106,6 @@ endif
 libsbi-objs-y += sbi_unpriv.o
 libsbi-objs-y += sbi_expected_trap.o
 libsbi-objs-y += sbi_cppc.o
+libsbi-objs-y += sbi_wdt.o
 libsbi-objs-$(CC_SUPPORT_VECTOR) += sbi_vector.o
 libsbi-objs-y += sbi_fp.o
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index acd2f8b6..a8ce0a63 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -35,6 +35,7 @@
 #include <sbi/sbi_tlb.h>
 #include <sbi/sbi_version.h>
 #include <sbi/sbi_unit_test.h>
+#include <sbi/sbi_wdt.h>
 
 #define BANNER                                              \
 	"   ____                    _____ ____ _____\n"     \
@@ -365,6 +366,13 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
 		sbi_hart_hang();
 	}
 
+	/* Initialise the watchdog*/
+	rc = sbi_watchdog_init();
+	if (rc) {
+		sbi_printf("%s: watchdog init failed (error %d)\n", __func__, rc);
+		sbi_hart_hang();
+	}
+
 	/*
 	 * Note: Finalize domains after HSM initialization
 	 * Note: Finalize domains before HART PMP configuration so
diff --git a/lib/sbi/sbi_wdt.c b/lib/sbi/sbi_wdt.c
new file mode 100644
index 00000000..988c6581
--- /dev/null
+++ b/lib/sbi/sbi_wdt.c
@@ -0,0 +1,455 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Qualcomm Inc.
+ *
+ * Authors:
+ *   Prajwal N <prajwal.n@oss.qualcomm.com>
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_bitops.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/riscv_locks.h>
+#include <sbi/sbi_heap.h>
+#include <sbi/sbi_irqchip.h>
+#include <sbi/sbi_timer.h>
+#include <sbi/sbi_wdt.h>
+#include <sbi/sbi_system.h>
+#include <sbi/sbi_console.h>
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_string.h>
+#include <sbi/sbi_hart_protection.h>
+
+/** Watchdog capabitlity - MSI */
+#define WDT_CAP_MSI_MASK	BIT(1)
+
+/** Watchdog capabitlity - SSE */
+#define WDT_CAP_SSE_MASK	BIT(0)
+
+/**
+ * Helpers to enable/disable channel capability bits
+ * _c: capability variable
+ * _m: capability mask
+ */
+#define CAP_ENABLE(_c, _m)	INSERT_FIELD(_c, _m, 1)
+#define CAP_DISABLE(_c, _m)	INSERT_FIELD(_c, _m, 0)
+#define CAP_GET(_c, _m)		EXTRACT_FIELD(_c, _m)
+
+/* Watchdog Permission Flags */
+#define WDT_ATTR_PERM_RO	BIT(0)
+#define WDT_ATTR_PERM_W	 BIT(1)
+#define WDT_ATTR_PERM_RW	(WDT_ATTR_PERM_RO) | (WDT_ATTR_PERM_W)
+
+static const u32 sbi_watchdog_attr_perm[SBI_WDT_ATTR_MAX] = {
+	[SBI_WDT_CAPABILITY]            = WDT_ATTR_PERM_RO,
+	[SBI_WDT_STATE]                 = WDT_ATTR_PERM_RO,
+	[SBI_WDT_MIN_PERIOD]            = WDT_ATTR_PERM_RO,
+	[SBI_WDT_PERIOD]                = WDT_ATTR_PERM_RW,
+	[SBI_WDT_TIME_LEFT]             = WDT_ATTR_PERM_RO,
+	[SBI_WDT_NOTIF_TIME]            = WDT_ATTR_PERM_RW,
+	[SBI_WDT_NOTIF_MSI_ADDR_LOW]    = WDT_ATTR_PERM_RW,
+	[SBI_WDT_NOTIF_MSI_ADDR_HIGH]   = WDT_ATTR_PERM_RW,
+	[SBI_WDT_NOTIF_MSI_DATA]        = WDT_ATTR_PERM_RW
+};
+
+/**
+ * SBI watchdog state
+ */
+typedef enum {
+	SBI_WDT_STOPPED = 0,
+	SBI_WDT_RUNNING	= 1,
+	SBI_WDT_PAUSED  = 2,
+	SBI_WDT_EXPIRED	= 3
+} sbi_wdt_state_t;
+
+/**
+ * SBI watchdog attributes
+ */
+struct sbi_watchdog_attrs {
+	/* MSI and SSE capability flags */
+	u32 wdt_capability;
+	/* Watchdog state */
+	u32 wdt_state;
+	/* Minimum watchdog timeout supported in us */
+	u32 wdt_min_period;
+	/* Watchdog timeout period in us */
+	u32 wdt_period;
+	/* Time left until watchdog expiry in us */
+	u32 wdt_time_left;
+	/* Watchdog pretimeout in us */
+	u32 wdt_notif_time;
+	/* MSI target address low 32-bit */
+	u32 wdt_notif_msi_addr_low;
+	/* MSI target address high 32-bit */
+	u32 wdt_notif_msi_addr_high;
+	/* MSI data */
+	u32 wdt_notif_msi_data;
+};
+
+struct sbi_watchdog {
+	/* Watchdog attributes */
+	struct sbi_watchdog_attrs wdt_attr;
+	/* Watchdog timeout event */
+	struct sbi_timer_event wdt_timer_ev;
+	/* Watchdog pretimeout event */
+	struct sbi_timer_event wdt_pretimeout_ev;
+	/* Watchdog spinlock */
+	spinlock_t wdt_lock;
+};
+
+/* Global pointer to the watchdog structure */
+static struct sbi_watchdog *sbi_system_watchdog;
+
+/** Make sure all the attributes are packed for direct memcpy in ATTR_READ */
+#define assert_field_offset(field, attr_offset)				\
+	_Static_assert(							\
+		((offsetof(struct sbi_watchdog_attrs, field)) /		\
+			sizeof(u32)) == attr_offset,			\
+		"field" #field						\
+		" from struct sbi_watchdog_attrs invalid offset, expected " #attr_offset)
+
+assert_field_offset(wdt_capability, SBI_WDT_CAPABILITY);
+assert_field_offset(wdt_state, SBI_WDT_STATE);
+assert_field_offset(wdt_min_period, SBI_WDT_MIN_PERIOD);
+assert_field_offset(wdt_period, SBI_WDT_PERIOD);
+assert_field_offset(wdt_time_left, SBI_WDT_TIME_LEFT);
+assert_field_offset(wdt_notif_time, SBI_WDT_NOTIF_TIME);
+assert_field_offset(wdt_notif_msi_addr_low, SBI_WDT_NOTIF_MSI_ADDR_LOW);
+assert_field_offset(wdt_notif_msi_addr_high, SBI_WDT_NOTIF_MSI_ADDR_HIGH);
+assert_field_offset(wdt_notif_msi_data, SBI_WDT_NOTIF_MSI_DATA);
+
+int sbi_watchdog_read_attribute(u32 attribute_id, u32* attribute_value)
+{
+	u64 current, deadline, tick_delta;
+	int ret = SBI_SUCCESS;
+
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+
+	switch (attribute_id) {
+	case SBI_WDT_TIME_LEFT:
+		/* Calculate the time left before expiry and update the attribute */
+		current = sbi_timer_value();
+		deadline = sbi_system_watchdog->wdt_timer_ev.time_stamp;
+		if (current >= deadline) {
+			sbi_system_watchdog->wdt_attr.wdt_time_left = 0;
+			break;
+		}
+		tick_delta = deadline - current;
+		sbi_system_watchdog->wdt_attr.wdt_time_left = sbi_timer_ticks_to_usec(tick_delta);
+		break;
+
+	default:
+		/* Return error if the attribute index is out of bound*/
+		if (attribute_id >= SBI_WDT_ATTR_MAX) {
+			ret = SBI_ERR_INVALID_PARAM;
+			goto out;
+		}
+		break;
+	}
+
+	u32 *wdt_attrs = (u32 *)&sbi_system_watchdog->wdt_attr;
+	*attribute_value = wdt_attrs[attribute_id];
+
+out:
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+	return ret;
+}
+
+int sbi_watchdog_write_attribute(u32 attribute_id, u32 attribute_value)
+{
+	int ret;
+
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+
+	/* Check if the attribute is writable */
+	if (!(sbi_watchdog_attr_perm[attribute_id] & WDT_ATTR_PERM_W)) {
+		ret = SBI_ERR_DENIED;
+		goto out;
+	}
+
+	switch (attribute_id) {
+	case SBI_WDT_PERIOD:
+		/* Return error if wdt_period passed is less than wdt_min_period */
+		if (attribute_value < sbi_system_watchdog->wdt_attr.wdt_min_period) {
+			ret = SBI_ERR_FAILED;
+			goto out;
+		}
+		break;
+
+	case SBI_WDT_NOTIF_TIME:
+		/* Ignore the write if the MSI capability is not enabled */
+		if (!CAP_GET(sbi_system_watchdog->wdt_attr.wdt_capability, WDT_CAP_MSI_MASK)) {
+			ret = SBI_SUCCESS;
+			goto out;
+		}
+
+		/* Returen error if the notif time is greater than the timeout period*/
+		if (attribute_value >= sbi_system_watchdog->wdt_attr.wdt_period) {
+			ret = SBI_ERR_FAILED;
+			goto out;
+		}
+		break;
+
+	case SBI_WDT_NOTIF_MSI_ADDR_LOW:
+	case SBI_WDT_NOTIF_MSI_ADDR_HIGH:
+	case SBI_WDT_NOTIF_MSI_DATA:
+		/* Ignore the write if the MSI capability is not enabled */
+		if (!CAP_GET(sbi_system_watchdog->wdt_attr.wdt_capability, WDT_CAP_MSI_MASK)) {
+			ret = SBI_SUCCESS;
+			goto out;
+		}
+
+		/*
+		 * The MSI address and data can be written only when
+		 * the notifications are disabled
+		 */
+		if (sbi_system_watchdog->wdt_attr.wdt_notif_time != 0) {
+			ret = SBI_ERR_FAILED;
+			goto out;
+		}
+		break;
+
+	default:
+		/* Return error if the attribute index is out of bound*/
+		if (attribute_id >= SBI_WDT_ATTR_MAX) {
+			ret = SBI_ERR_INVALID_PARAM;
+			goto out;
+		}
+		break;
+	}
+
+	u32 *wdt_attrs = (u32 *)&sbi_system_watchdog->wdt_attr;
+	wdt_attrs[attribute_id] = attribute_value;
+
+	ret = SBI_SUCCESS;
+
+out:
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+	return ret;
+}
+
+int sbi_watchdog_write_notif_msi_message(u32 msi_addr_low, u32 msi_addr_high, u32 msi_data)
+{
+	int ret;
+
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+
+	/* Ignore the write if the MSI capability is not enabled */
+	if (!CAP_GET(sbi_system_watchdog->wdt_attr.wdt_capability, WDT_CAP_MSI_MASK)) {
+		ret = SBI_SUCCESS;
+		goto out;
+	}
+
+	/* The MSI address and data can be written only when the notifications are disabled */
+	if (sbi_system_watchdog->wdt_attr.wdt_notif_time != 0) {
+		ret = SBI_EINVAL;
+		goto out;
+	}
+
+	u32 *wdt_attrs = (u32 *)&sbi_system_watchdog->wdt_attr;
+	wdt_attrs[SBI_WDT_NOTIF_MSI_ADDR_LOW] = msi_addr_low;
+	wdt_attrs[SBI_WDT_NOTIF_MSI_ADDR_HIGH] = msi_addr_high;
+	wdt_attrs[SBI_WDT_NOTIF_MSI_DATA] = msi_data;
+
+	ret = SBI_SUCCESS;
+
+out:
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+	return ret;
+}
+
+static void sbi_watchdog_pretimeout_cleanup(struct sbi_timer_event *ev)
+{
+	/* Nothing to do */
+}
+
+static void sbi_watchdog_pretimeout_callback(struct sbi_timer_event *ev,
+					     struct sbi_timer_event_restart *restart)
+{
+	u64 msi_addr;
+	u32 msi_data;
+
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+	/* Calculate the MSI address using the low and high addresses*/
+	msi_addr = (((u64)sbi_system_watchdog->wdt_attr.wdt_notif_msi_addr_high << 32 ) |
+					sbi_system_watchdog->wdt_attr.wdt_notif_msi_addr_low);
+	msi_data = sbi_system_watchdog->wdt_attr.wdt_notif_msi_data;
+
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+
+	sbi_hart_protection_temp_map_range((unsigned long)msi_addr, sizeof(u32));
+	/* Write the MSI data to the MSI address*/
+	writel(msi_data, (void *)(unsigned long)msi_addr);
+	sbi_hart_protection_temp_unmap_range((unsigned long)msi_addr, sizeof(u32));
+}
+
+static void sbi_watchdog_event_cleanup(struct sbi_timer_event *ev)
+{
+	/* Nothing to do */
+}
+
+static void sbi_watchdog_expired_callback(struct sbi_timer_event *ev,
+					  struct sbi_timer_event_restart *restart)
+{
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+
+	sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_EXPIRED;
+	/* Trigger the system reboot*/
+	sbi_system_reset(SBI_SRST_RESET_TYPE_WARM_REBOOT, SBI_SRST_RESET_REASON_NONE);
+
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+}
+
+static void sbi_watchdog_enable_timer_events()
+{
+	u64 timeout, pretimeout;
+	u32 pretimeout_us;
+
+	/* Restart the pretimeout event only if the wdt_notif_time is non zero*/
+	if (sbi_system_watchdog->wdt_attr.wdt_notif_time != 0) {
+		pretimeout_us = sbi_system_watchdog->wdt_attr.wdt_period -
+				sbi_system_watchdog->wdt_attr.wdt_notif_time;
+		pretimeout = sbi_timer_value() + sbi_timer_compute_udelta(pretimeout_us);
+
+		sbi_timer_event_start(&sbi_system_watchdog->wdt_pretimeout_ev, pretimeout);
+	}
+
+	/* Restart the Watchdog timeout event only if the wdt_period is non zero*/
+	if (sbi_system_watchdog->wdt_attr.wdt_period != 0) {
+		timeout = sbi_timer_value() +
+			  sbi_timer_compute_udelta(sbi_system_watchdog->wdt_attr.wdt_period);
+		sbi_timer_event_start(&sbi_system_watchdog->wdt_timer_ev, timeout);
+	}
+}
+
+int sbi_watchdog_start(void)
+{
+	int ret;
+
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+
+	/* Return error if the watchdog is not in SBI_WDT_STOPPED state*/
+	if (sbi_system_watchdog->wdt_attr.wdt_state != SBI_WDT_STOPPED) {
+		ret = SBI_ERR_INVALID_STATE;
+		goto out;
+	}
+
+	sbi_watchdog_enable_timer_events();
+
+	sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_RUNNING;
+	ret = SBI_SUCCESS;
+
+out:
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+	return ret;
+}
+
+int sbi_watchdog_stop(void)
+{
+	int ret;
+
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+
+	/* Return error if the watchdog is already in SBI_WDT_STOPPED state */
+	if (sbi_system_watchdog->wdt_attr.wdt_state == SBI_WDT_STOPPED) {
+		ret = SBI_ERR_INVALID_STATE;
+		goto out;
+	}
+
+	/* Stop both the pretimeout and expiry events */
+	sbi_timer_event_stop(&sbi_system_watchdog->wdt_pretimeout_ev);
+	sbi_timer_event_stop(&sbi_system_watchdog->wdt_timer_ev);
+
+	sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_STOPPED;
+	sbi_system_watchdog->wdt_attr.wdt_time_left = 0;
+
+	ret = SBI_SUCCESS;
+
+out:
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+	return ret;
+}
+
+int sbi_watchdog_pat(void)
+{
+	int ret;
+
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+
+	/* Return error if the watchdog is not in SBI_WDT_RUNNING state*/
+	if (sbi_system_watchdog->wdt_attr.wdt_state != SBI_WDT_RUNNING) {
+		ret = SBI_ERR_INVALID_STATE;
+		goto out;
+	}
+
+	sbi_watchdog_enable_timer_events();
+	ret = SBI_SUCCESS;
+
+out:
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+	return ret;
+}
+
+static void sbi_watchdog_init_attributes(void)
+{
+	const struct sbi_timer_device *tdev;
+	unsigned long timer_freq;
+	u32 capability = 0;
+
+	spin_lock(&sbi_system_watchdog->wdt_lock);
+
+	sbi_memset(&sbi_system_watchdog->wdt_attr, 0, sizeof(struct sbi_watchdog_attrs));
+
+	/* Retrieve the MSI capability from irqchip */
+	if (sbi_irqchip_find_device_by_caps(SBI_IRQCHIP_CAPS_MSI, NULL))
+		capability = CAP_ENABLE(capability, WDT_CAP_MSI_MASK);
+
+	sbi_system_watchdog->wdt_attr.wdt_capability = capability;
+
+	sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_STOPPED;
+
+	/* Set the min period based on the timer frequency */
+	tdev = sbi_timer_get_device();
+	if (tdev != NULL) {
+		timer_freq = tdev->timer_freq;
+		/* Ceil division to ensure the result is non-zero */
+		sbi_system_watchdog->wdt_attr.wdt_min_period =
+					(u32)((SEC_TO_MICROSEC + timer_freq - 1) / timer_freq);
+	}
+
+	spin_unlock(&sbi_system_watchdog->wdt_lock);
+}
+
+int sbi_watchdog_init(void)
+{
+	/* Allocate memory for global watchdog structure sbi_system_watchdog */
+	sbi_system_watchdog = (struct sbi_watchdog*)sbi_zalloc(sizeof(struct sbi_watchdog));
+
+	if(!sbi_system_watchdog) {
+		return SBI_ENOMEM;
+	}
+
+	SPIN_LOCK_INIT(sbi_system_watchdog->wdt_lock);
+	SBI_INIT_TIMER_EVENT(&sbi_system_watchdog->wdt_timer_ev,
+			     sbi_watchdog_expired_callback,
+			     sbi_watchdog_event_cleanup, NULL);
+	SBI_INIT_TIMER_EVENT(&sbi_system_watchdog->wdt_pretimeout_ev,
+			     sbi_watchdog_pretimeout_callback,
+			     sbi_watchdog_pretimeout_cleanup, NULL);
+
+	/* Initialize the default watchdog attributes */
+	sbi_watchdog_init_attributes();
+
+	return SBI_SUCCESS;
+}
+
+int sbi_watchdog_exit(void)
+{
+	/* Clean up the global watchdog */
+	sbi_free(sbi_system_watchdog);
+
+	return 0;
+}
-- 
2.43.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/4] lib: sbi: Add ecall handler for SBI watchdog
  2026-10-02  8:30 [PATCH 0/4] RISC-V SBI watchdog support Prajwal N
                   ` (2 preceding siblings ...)
  2026-10-02  8:30 ` [PATCH 3/4] lib: sbi: Add SBI watchdog framework Prajwal N
@ 2026-10-02  8:30 ` Prajwal N
  3 siblings, 0 replies; 8+ messages in thread
From: Prajwal N @ 2026-10-02  8:30 UTC (permalink / raw)
  To: anup; +Cc: opensbi, prajwal.n.oss, Prajwal N

Update the Kconfig and build infrastructure to include
SBI ecall handler for watchdog.

Implement ecall handler functionality to delegate the
ecall to SBI watchdog framework

Signed-off-by: Prajwal N <prajwal.n@oss.qualcomm.com>
---
 lib/sbi/Kconfig         |  4 +++
 lib/sbi/objects.mk      |  3 ++
 lib/sbi/sbi_ecall_wdt.c | 79 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)
 create mode 100644 lib/sbi/sbi_ecall_wdt.c

diff --git a/lib/sbi/Kconfig b/lib/sbi/Kconfig
index 24132eaa..6fd965d5 100644
--- a/lib/sbi/Kconfig
+++ b/lib/sbi/Kconfig
@@ -95,4 +95,8 @@ config SBI_ECALL_SSE
 config SBI_ECALL_MPXY
 	bool "MPXY extension"
 	default y
+
+config SBI_ECALL_WDT
+	bool "WDT extension"
+	default y
 endmenu
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index c8bdc94a..847aee89 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -46,6 +46,9 @@ libsbi-objs-$(CONFIG_SBI_ECALL_DBCN) += sbi_ecall_dbcn.o
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_CPPC) += ecall_cppc
 libsbi-objs-$(CONFIG_SBI_ECALL_CPPC) += sbi_ecall_cppc.o
 
+carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_WDT) += ecall_wdt
+libsbi-objs-$(CONFIG_SBI_ECALL_WDT) += sbi_ecall_wdt.o
+
 carray-sbi_ecall_exts-$(CONFIG_SBI_ECALL_FWFT) += ecall_fwft
 libsbi-objs-$(CONFIG_SBI_ECALL_FWFT) += sbi_ecall_fwft.o
 
diff --git a/lib/sbi/sbi_ecall_wdt.c b/lib/sbi/sbi_ecall_wdt.c
new file mode 100644
index 00000000..81b3e174
--- /dev/null
+++ b/lib/sbi/sbi_ecall_wdt.c
@@ -0,0 +1,79 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Qualcomm Inc.
+ *
+ * Authors:
+ *   Prajwal N <prajwal.n@oss.qualcomm.com>
+ */
+
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_trap.h>
+#include <sbi/sbi_wdt.h>
+
+/**
+ * OpenSBI watchdog ecall handler
+ * @param extid OpenSBI extension ID
+ * @param funcid OpenSBI function ID corresponding to the extension ID
+ * @param regs Trap registers for arguments
+ * @param out Carry the return value
+ * @return integer error value
+ */
+static int sbi_ecall_wdt_handler(unsigned long extid, unsigned long funcid,
+			                        struct sbi_trap_regs *regs,
+	                                struct sbi_ecall_return *out)
+{
+	int ret;
+	u32 attribute_value = 0;
+	ret = SBI_ERR_FAILED;
+
+	switch (funcid) {
+	case SBI_EXT_WATCHDOG_READ_ATTRIBUTE:
+		ret = sbi_watchdog_read_attribute(regs->a0, &attribute_value);
+		out->value = attribute_value;
+		break;
+
+	case SBI_EXT_WATCHDOG_WRITE_ATTRIBUTE:
+		ret = sbi_watchdog_write_attribute(regs->a0, regs->a1);
+		break;
+
+	case SBI_EXT_WATCHDOG_WRITE_NOTIF_MSI_MESSAGE:
+		ret = sbi_watchdog_write_notif_msi_message(regs->a0, regs->a1, regs->a2);
+		break;
+
+	case SBI_EXT_WATCHDOG_START:
+		ret = sbi_watchdog_start();
+		break;
+
+	case SBI_EXT_WATCHDOG_STOP:
+		ret = sbi_watchdog_stop();
+		break;
+
+	case SBI_EXT_WATCHDOG_PAT:
+		ret = sbi_watchdog_pat();
+		break;
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+struct sbi_ecall_extension ecall_wdt;
+
+static int sbi_ecall_wdt_register_extensions(void)
+{
+	return sbi_ecall_register_extension(&ecall_wdt);
+}
+
+struct sbi_ecall_extension ecall_wdt = {
+	.name                   = "sbi-wdt",
+	.extid_start            = SBI_EXT_WDT,
+	.extid_end              = SBI_EXT_WDT,
+	.experimental           = true,
+	.register_extensions    = sbi_ecall_wdt_register_extensions,
+	.handle                 = sbi_ecall_wdt_handler,
+};
-- 
2.43.0


-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/4] lib: sbi: Add SBI watchdog framework
  2026-10-02  8:30 ` [PATCH 3/4] lib: sbi: Add SBI watchdog framework Prajwal N
@ 2026-10-05  3:33   ` Rahul Pathak
  2026-10-05  9:16   ` Rahul Pathak
  2026-10-23  4:55   ` Himanshu Chauhan
  2 siblings, 0 replies; 8+ messages in thread
From: Rahul Pathak @ 2026-10-05  3:33 UTC (permalink / raw)
  To: Prajwal N; +Cc: anup, opensbi, prajwal.n.oss

On Fri, Oct 2, 2026 at 2:01 PM Prajwal N <prajwal.n@oss.qualcomm.com> wrote:
>
> Update the build infrastructure to include the SBI
> watchdog compilation.
>
> Implement the SBI watchdog functionality including
> start, stop, pat, read and write attributes,
> pretimeout and timeout handlers.
>
> Signed-off-by: Prajwal N <prajwal.n@oss.qualcomm.com>
> ---
>  include/sbi/sbi_wdt.h |  72 +++++++
>  lib/sbi/objects.mk    |   1 +
>  lib/sbi/sbi_init.c    |   8 +
>  lib/sbi/sbi_wdt.c     | 455 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 536 insertions(+)
>  create mode 100644 include/sbi/sbi_wdt.h
>  create mode 100644 lib/sbi/sbi_wdt.c
>
> +
> +
> +static void sbi_watchdog_expired_callback(struct sbi_timer_event *ev,
> +                                         struct sbi_timer_event_restart *restart)
> +{
> +       spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +       sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_EXPIRED;
> +       /* Trigger the system reboot*/
> +       sbi_system_reset(SBI_SRST_RESET_TYPE_WARM_REBOOT, SBI_SRST_RESET_REASON_NONE);

Better to call the sbi_system_reset after the spinlock unlock

> +
> +       spin_unlock(&sbi_system_watchdog->wdt_lock);
> +}
> +
> +static void sbi_watchdog_enable_timer_events()
> +{
> +       u64 timeout, pretimeout;
> +       u32 pretimeout_us;
> +
> +       /* Restart the pretimeout event only if the wdt_notif_time is non zero*/
> +       if (sbi_system_watchdog->wdt_attr.wdt_notif_time != 0) {
> +               pretimeout_us = sbi_system_watchdog->wdt_attr.wdt_period -
> +                               sbi_system_watchdog->wdt_attr.wdt_notif_time;
> +               pretimeout = sbi_timer_value() + sbi_timer_compute_udelta(pretimeout_us);
> +
> +               sbi_timer_event_start(&sbi_system_watchdog->wdt_pretimeout_ev, pretimeout);
> +       }
> +
> +       /* Restart the Watchdog timeout event only if the wdt_period is non zero*/
> +       if (sbi_system_watchdog->wdt_attr.wdt_period != 0) {
> +               timeout = sbi_timer_value() +
> +                         sbi_timer_compute_udelta(sbi_system_watchdog->wdt_attr.wdt_period);
> +               sbi_timer_event_start(&sbi_system_watchdog->wdt_timer_ev, timeout);
> +       }
> +}
> +

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/4] lib: sbi: Add SBI watchdog framework
  2026-10-02  8:30 ` [PATCH 3/4] lib: sbi: Add SBI watchdog framework Prajwal N
  2026-10-05  3:33   ` Rahul Pathak
@ 2026-10-05  9:16   ` Rahul Pathak
  2026-10-23  4:55   ` Himanshu Chauhan
  2 siblings, 0 replies; 8+ messages in thread
From: Rahul Pathak @ 2026-10-05  9:16 UTC (permalink / raw)
  To: Prajwal N; +Cc: anup, opensbi, prajwal.n.oss

On Fri, Oct 2, 2026 at 2:01 PM Prajwal N <prajwal.n@oss.qualcomm.com> wrote:
>
> Update the build infrastructure to include the SBI
> watchdog compilation.
>
> Implement the SBI watchdog functionality including
> start, stop, pat, read and write attributes,
> pretimeout and timeout handlers.
>
> Signed-off-by: Prajwal N <prajwal.n@oss.qualcomm.com>
> ---
>  include/sbi/sbi_wdt.h |  72 +++++++
>  lib/sbi/objects.mk    |   1 +
>  lib/sbi/sbi_init.c    |   8 +
>  lib/sbi/sbi_wdt.c     | 455 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 536 insertions(+)
>  create mode 100644 include/sbi/sbi_wdt.h
>  create mode 100644 lib/sbi/sbi_wdt.c
>
> +
> +int sbi_watchdog_write_attribute(u32 attribute_id, u32 attribute_value)
> +{
> +       int ret;
> +
> +       spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +       /* Check if the attribute is writable */
> +       if (!(sbi_watchdog_attr_perm[attribute_id] & WDT_ATTR_PERM_W)) {

attribute_id must be validated here before it's used for any access.

> +               ret = SBI_ERR_DENIED;
> +               goto out;
> +       }
> +
> +       switch (attribute_id) {
> +       case SBI_WDT_PERIOD:
> +               /* Return error if wdt_period passed is less than wdt_min_period */
> +               if (attribute_value < sbi_system_watchdog->wdt_attr.wdt_min_period) {
> +                       ret = SBI_ERR_FAILED;
> +                       goto out;
> +               }
> +               break;
> +
> +       case SBI_WDT_NOTIF_TIME:
> +               /* Ignore the write if the MSI capability is not enabled */
> +               if (!CAP_GET(sbi_system_watchdog->wdt_attr.wdt_capability, WDT_CAP_MSI_MASK)) {
> +                       ret = SBI_SUCCESS;
> +                       goto out;
> +               }
> +
> +               /* Returen error if the notif time is greater than the timeout period*/
> +               if (attribute_value >= sbi_system_watchdog->wdt_attr.wdt_period) {
> +                       ret = SBI_ERR_FAILED;
> +                       goto out;
> +               }
> +               break;
> +
> +       case SBI_WDT_NOTIF_MSI_ADDR_LOW:
> +       case SBI_WDT_NOTIF_MSI_ADDR_HIGH:
> +       case SBI_WDT_NOTIF_MSI_DATA:
> +               /* Ignore the write if the MSI capability is not enabled */
> +               if (!CAP_GET(sbi_system_watchdog->wdt_attr.wdt_capability, WDT_CAP_MSI_MASK)) {
> +                       ret = SBI_SUCCESS;
> +                       goto out;
> +               }
> +
> +               /*
> +                * The MSI address and data can be written only when
> +                * the notifications are disabled
> +                */
> +               if (sbi_system_watchdog->wdt_attr.wdt_notif_time != 0) {
> +                       ret = SBI_ERR_FAILED;
> +                       goto out;
> +               }
> +               break;
> +
> +       default:
> +               /* Return error if the attribute index is out of bound*/
> +               if (attribute_id >= SBI_WDT_ATTR_MAX) {
> +                       ret = SBI_ERR_INVALID_PARAM;
> +                       goto out;
> +               }
> +               break;
> +       }
> +
> +       u32 *wdt_attrs = (u32 *)&sbi_system_watchdog->wdt_attr;
> +       wdt_attrs[attribute_id] = attribute_value;
> +
> +       ret = SBI_SUCCESS;
> +
> +out:
> +       spin_unlock(&sbi_system_watchdog->wdt_lock);
> +       return ret;
> +}
> +

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/4] lib: sbi: Add SBI watchdog framework
  2026-10-02  8:30 ` [PATCH 3/4] lib: sbi: Add SBI watchdog framework Prajwal N
  2026-10-05  3:33   ` Rahul Pathak
  2026-10-05  9:16   ` Rahul Pathak
@ 2026-10-23  4:55   ` Himanshu Chauhan
  2 siblings, 0 replies; 8+ messages in thread
From: Himanshu Chauhan @ 2026-10-23  4:55 UTC (permalink / raw)
  To: Prajwal N; +Cc: anup, opensbi, prajwal.n.oss

Hi Prajwal,

On Fri, Oct 02, 2026 at 02:00:39PM +0530, Prajwal N wrote:
> Update the build infrastructure to include the SBI
> watchdog compilation.
> 
> Implement the SBI watchdog functionality including
> start, stop, pat, read and write attributes,
> pretimeout and timeout handlers.
> 
> Signed-off-by: Prajwal N <prajwal.n@oss.qualcomm.com>
> ---
>  include/sbi/sbi_wdt.h |  72 +++++++
>  lib/sbi/objects.mk    |   1 +
>  lib/sbi/sbi_init.c    |   8 +
>  lib/sbi/sbi_wdt.c     | 455 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 536 insertions(+)
>  create mode 100644 include/sbi/sbi_wdt.h
>  create mode 100644 lib/sbi/sbi_wdt.c
> 
> diff --git a/include/sbi/sbi_wdt.h b/include/sbi/sbi_wdt.h
> new file mode 100644
> index 00000000..43f866dc
> --- /dev/null
> +++ b/include/sbi/sbi_wdt.h
> @@ -0,0 +1,72 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2026 Qualcomm Inc.
> + *
> + * Authors:
> + *   Prajwal N <prajwal.n@oss.qualcomm.com>
> + */
> +
> +#ifndef __SBI_WDT_H__
> +#define __SBI_WDT_H__
> +
> +/**
> + * Read the watchdog attribute
> + * @param attribute_id The wdt attribute id to be read
> + * @param attribute_value The value of attribute returned
> + * @return int error
> + */
> +int sbi_watchdog_read_attribute(u32 attribute_id, u32* attribute_value);
> +
> +/**
> + * Write the watchdog attribute
> + * @param attribute_id The wdt attribute id to be written
> + * @param attribute_value The wdt attribute value to be written
> + * @return int error
> + */
> +int sbi_watchdog_write_attribute(u32 attribute_id, u32 attribute_value);
> +
> +/**
> + * Write the watchdog MSI message attribute
> + * @param msi_addr_low The value of MSI low address
> + * @param msi_addr_high The value of MSI high address
> + * @param msi_data The value of MSI data
> + * @return int error
> + */
> +int sbi_watchdog_write_notif_msi_message(u32 msi_addr_low, u32 msi_addr_high, u32 msi_data);
> +
> +/**
> + * Start the watchdog
> + * @param void
> + * @return int error
> + */
> +int sbi_watchdog_start(void);
> +
> +/**
> + * Stop the watchdog
> + * @param void
> + * @return int error
> + */
> +int sbi_watchdog_stop(void);
> +
> +/**
> + * Pat the watchdog
> + * @param void
> + * @return int error
> + */
> +int sbi_watchdog_pat(void);
> +
> +/**
> + * Initialize the watchdog
> + * @param void
> + * @return int error
> + */
> +int sbi_watchdog_init(void);
> +
> +/**
> + * Remove the watchdog
> + * @param void
> + * @return int error
> + */
> +int sbi_watchdog_exit(void);
> +#endif
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index ae27d0c5..c8bdc94a 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -106,5 +106,6 @@ endif
>  libsbi-objs-y += sbi_unpriv.o
>  libsbi-objs-y += sbi_expected_trap.o
>  libsbi-objs-y += sbi_cppc.o
> +libsbi-objs-y += sbi_wdt.o
>  libsbi-objs-$(CC_SUPPORT_VECTOR) += sbi_vector.o
>  libsbi-objs-y += sbi_fp.o
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index acd2f8b6..a8ce0a63 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -35,6 +35,7 @@
>  #include <sbi/sbi_tlb.h>
>  #include <sbi/sbi_version.h>
>  #include <sbi/sbi_unit_test.h>
> +#include <sbi/sbi_wdt.h>
>  
>  #define BANNER                                              \
>  	"   ____                    _____ ____ _____\n"     \
> @@ -365,6 +366,13 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
>  		sbi_hart_hang();
>  	}
>  
> +	/* Initialise the watchdog*/
> +	rc = sbi_watchdog_init();
> +	if (rc) {
> +		sbi_printf("%s: watchdog init failed (error %d)\n", __func__, rc);
> +		sbi_hart_hang();
> +	}
> +
>  	/*
>  	 * Note: Finalize domains after HSM initialization
>  	 * Note: Finalize domains before HART PMP configuration so
> diff --git a/lib/sbi/sbi_wdt.c b/lib/sbi/sbi_wdt.c
> new file mode 100644
> index 00000000..988c6581
> --- /dev/null
> +++ b/lib/sbi/sbi_wdt.c
> @@ -0,0 +1,455 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2026 Qualcomm Inc.
> + *
> + * Authors:
> + *   Prajwal N <prajwal.n@oss.qualcomm.com>
> + */
> +
> +#include <sbi/riscv_asm.h>
> +#include <sbi/sbi_error.h>
> +#include <sbi/sbi_ecall.h>
> +#include <sbi/sbi_bitops.h>
> +#include <sbi/sbi_ecall_interface.h>
> +#include <sbi/riscv_locks.h>
> +#include <sbi/sbi_heap.h>
> +#include <sbi/sbi_irqchip.h>
> +#include <sbi/sbi_timer.h>
> +#include <sbi/sbi_wdt.h>
> +#include <sbi/sbi_system.h>
> +#include <sbi/sbi_console.h>
> +#include <sbi/riscv_io.h>
> +#include <sbi/sbi_string.h>
> +#include <sbi/sbi_hart_protection.h>
> +
> +/** Watchdog capabitlity - MSI */
> +#define WDT_CAP_MSI_MASK	BIT(1)
> +
> +/** Watchdog capabitlity - SSE */
> +#define WDT_CAP_SSE_MASK	BIT(0)
> +
> +/**
> + * Helpers to enable/disable channel capability bits
> + * _c: capability variable
> + * _m: capability mask
> + */
> +#define CAP_ENABLE(_c, _m)	INSERT_FIELD(_c, _m, 1)
> +#define CAP_DISABLE(_c, _m)	INSERT_FIELD(_c, _m, 0)
> +#define CAP_GET(_c, _m)		EXTRACT_FIELD(_c, _m)
> +
> +/* Watchdog Permission Flags */
> +#define WDT_ATTR_PERM_RO	BIT(0)
> +#define WDT_ATTR_PERM_W	 BIT(1)
> +#define WDT_ATTR_PERM_RW	(WDT_ATTR_PERM_RO) | (WDT_ATTR_PERM_W)
> +
> +static const u32 sbi_watchdog_attr_perm[SBI_WDT_ATTR_MAX] = {
> +	[SBI_WDT_CAPABILITY]            = WDT_ATTR_PERM_RO,
> +	[SBI_WDT_STATE]                 = WDT_ATTR_PERM_RO,
> +	[SBI_WDT_MIN_PERIOD]            = WDT_ATTR_PERM_RO,
> +	[SBI_WDT_PERIOD]                = WDT_ATTR_PERM_RW,
> +	[SBI_WDT_TIME_LEFT]             = WDT_ATTR_PERM_RO,
> +	[SBI_WDT_NOTIF_TIME]            = WDT_ATTR_PERM_RW,
> +	[SBI_WDT_NOTIF_MSI_ADDR_LOW]    = WDT_ATTR_PERM_RW,
> +	[SBI_WDT_NOTIF_MSI_ADDR_HIGH]   = WDT_ATTR_PERM_RW,
> +	[SBI_WDT_NOTIF_MSI_DATA]        = WDT_ATTR_PERM_RW
> +};
> +
> +/**
> + * SBI watchdog state
> + */
> +typedef enum {
> +	SBI_WDT_STOPPED = 0,
> +	SBI_WDT_RUNNING	= 1,
> +	SBI_WDT_PAUSED  = 2,
> +	SBI_WDT_EXPIRED	= 3
> +} sbi_wdt_state_t;
> +
> +/**
> + * SBI watchdog attributes
> + */
> +struct sbi_watchdog_attrs {
> +	/* MSI and SSE capability flags */
> +	u32 wdt_capability;
> +	/* Watchdog state */
> +	u32 wdt_state;
> +	/* Minimum watchdog timeout supported in us */
> +	u32 wdt_min_period;
> +	/* Watchdog timeout period in us */
> +	u32 wdt_period;
> +	/* Time left until watchdog expiry in us */
> +	u32 wdt_time_left;
> +	/* Watchdog pretimeout in us */
> +	u32 wdt_notif_time;
> +	/* MSI target address low 32-bit */
> +	u32 wdt_notif_msi_addr_low;
> +	/* MSI target address high 32-bit */
> +	u32 wdt_notif_msi_addr_high;
> +	/* MSI data */
> +	u32 wdt_notif_msi_data;
> +};
> +
> +struct sbi_watchdog {
> +	/* Watchdog attributes */
> +	struct sbi_watchdog_attrs wdt_attr;
> +	/* Watchdog timeout event */
> +	struct sbi_timer_event wdt_timer_ev;
> +	/* Watchdog pretimeout event */
> +	struct sbi_timer_event wdt_pretimeout_ev;
> +	/* Watchdog spinlock */
> +	spinlock_t wdt_lock;
> +};
> +
> +/* Global pointer to the watchdog structure */
> +static struct sbi_watchdog *sbi_system_watchdog;
> +
> +/** Make sure all the attributes are packed for direct memcpy in ATTR_READ */
> +#define assert_field_offset(field, attr_offset)				\
> +	_Static_assert(							\
> +		((offsetof(struct sbi_watchdog_attrs, field)) /		\
> +			sizeof(u32)) == attr_offset,			\
> +		"field" #field						\
> +		" from struct sbi_watchdog_attrs invalid offset, expected " #attr_offset)
> +
> +assert_field_offset(wdt_capability, SBI_WDT_CAPABILITY);
> +assert_field_offset(wdt_state, SBI_WDT_STATE);
> +assert_field_offset(wdt_min_period, SBI_WDT_MIN_PERIOD);
> +assert_field_offset(wdt_period, SBI_WDT_PERIOD);
> +assert_field_offset(wdt_time_left, SBI_WDT_TIME_LEFT);
> +assert_field_offset(wdt_notif_time, SBI_WDT_NOTIF_TIME);
> +assert_field_offset(wdt_notif_msi_addr_low, SBI_WDT_NOTIF_MSI_ADDR_LOW);
> +assert_field_offset(wdt_notif_msi_addr_high, SBI_WDT_NOTIF_MSI_ADDR_HIGH);
> +assert_field_offset(wdt_notif_msi_data, SBI_WDT_NOTIF_MSI_DATA);
> +
> +int sbi_watchdog_read_attribute(u32 attribute_id, u32* attribute_value)
> +{
> +	u64 current, deadline, tick_delta;
> +	int ret = SBI_SUCCESS;
> +
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +	switch (attribute_id) {
> +	case SBI_WDT_TIME_LEFT:
> +		/* Calculate the time left before expiry and update the attribute */
> +		current = sbi_timer_value();
> +		deadline = sbi_system_watchdog->wdt_timer_ev.time_stamp;
> +		if (current >= deadline) {
> +			sbi_system_watchdog->wdt_attr.wdt_time_left = 0;
> +			break;
> +		}
> +		tick_delta = deadline - current;
> +		sbi_system_watchdog->wdt_attr.wdt_time_left = sbi_timer_ticks_to_usec(tick_delta);
> +		break;
> +
> +	default:
> +		/* Return error if the attribute index is out of bound*/
> +		if (attribute_id >= SBI_WDT_ATTR_MAX) {
> +			ret = SBI_ERR_INVALID_PARAM;
> +			goto out;
> +		}
> +		break;
> +	}
> +
> +	u32 *wdt_attrs = (u32 *)&sbi_system_watchdog->wdt_attr;
> +	*attribute_value = wdt_attrs[attribute_id];
> +
> +out:
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +	return ret;
> +}
> +
> +int sbi_watchdog_write_attribute(u32 attribute_id, u32 attribute_value)
> +{
> +	int ret;
> +
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +	/* Check if the attribute is writable */
> +	if (!(sbi_watchdog_attr_perm[attribute_id] & WDT_ATTR_PERM_W)) {
This is unbounded access. Please validate attribute_id against SBI_WDT_ATTR_MAX before access.

> +		ret = SBI_ERR_DENIED;
> +		goto out;
> +	}
> +
> +	switch (attribute_id) {
> +	case SBI_WDT_PERIOD:
> +		/* Return error if wdt_period passed is less than wdt_min_period */
> +		if (attribute_value < sbi_system_watchdog->wdt_attr.wdt_min_period) {
> +			ret = SBI_ERR_FAILED;
> +			goto out;
> +		}
> +		break;
> +
> +	case SBI_WDT_NOTIF_TIME:
> +		/* Ignore the write if the MSI capability is not enabled */
> +		if (!CAP_GET(sbi_system_watchdog->wdt_attr.wdt_capability, WDT_CAP_MSI_MASK)) {
> +			ret = SBI_SUCCESS;
> +			goto out;
> +		}
> +
> +		/* Returen error if the notif time is greater than the timeout period*/
Typo.

> +		if (attribute_value >= sbi_system_watchdog->wdt_attr.wdt_period) {
> +			ret = SBI_ERR_FAILED;
> +			goto out;
> +		}
> +		break;
> +
> +	case SBI_WDT_NOTIF_MSI_ADDR_LOW:
> +	case SBI_WDT_NOTIF_MSI_ADDR_HIGH:
> +	case SBI_WDT_NOTIF_MSI_DATA:
> +		/* Ignore the write if the MSI capability is not enabled */
> +		if (!CAP_GET(sbi_system_watchdog->wdt_attr.wdt_capability, WDT_CAP_MSI_MASK)) {
> +			ret = SBI_SUCCESS;
> +			goto out;
> +		}
> +
> +		/*
> +		 * The MSI address and data can be written only when
> +		 * the notifications are disabled
> +		 */
> +		if (sbi_system_watchdog->wdt_attr.wdt_notif_time != 0) {
> +			ret = SBI_ERR_FAILED;
> +			goto out;
> +		}
> +		break;
> +
> +	default:
> +		/* Return error if the attribute index is out of bound*/
> +		if (attribute_id >= SBI_WDT_ATTR_MAX) {
> +			ret = SBI_ERR_INVALID_PARAM;
> +			goto out;
> +		}
> +		break;
> +	}
> +
> +	u32 *wdt_attrs = (u32 *)&sbi_system_watchdog->wdt_attr;
> +	wdt_attrs[attribute_id] = attribute_value;
> +
> +	ret = SBI_SUCCESS;
> +
> +out:
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +	return ret;
> +}
> +
> +int sbi_watchdog_write_notif_msi_message(u32 msi_addr_low, u32 msi_addr_high, u32 msi_data)
> +{
> +	int ret;
> +
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +	/* Ignore the write if the MSI capability is not enabled */
> +	if (!CAP_GET(sbi_system_watchdog->wdt_attr.wdt_capability, WDT_CAP_MSI_MASK)) {
> +		ret = SBI_SUCCESS;
> +		goto out;
> +	}
> +
> +	/* The MSI address and data can be written only when the notifications are disabled */
> +	if (sbi_system_watchdog->wdt_attr.wdt_notif_time != 0) {
> +		ret = SBI_EINVAL;
> +		goto out;
> +	}
> +
> +	u32 *wdt_attrs = (u32 *)&sbi_system_watchdog->wdt_attr;
> +	wdt_attrs[SBI_WDT_NOTIF_MSI_ADDR_LOW] = msi_addr_low;
> +	wdt_attrs[SBI_WDT_NOTIF_MSI_ADDR_HIGH] = msi_addr_high;
> +	wdt_attrs[SBI_WDT_NOTIF_MSI_DATA] = msi_data;
> +
> +	ret = SBI_SUCCESS;
> +
> +out:
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +	return ret;
> +}
> +
> +static void sbi_watchdog_pretimeout_cleanup(struct sbi_timer_event *ev)
> +{
> +	/* Nothing to do */
> +}
> +
> +static void sbi_watchdog_pretimeout_callback(struct sbi_timer_event *ev,
> +					     struct sbi_timer_event_restart *restart)
> +{
> +	u64 msi_addr;
> +	u32 msi_data;
> +
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +	/* Calculate the MSI address using the low and high addresses*/
> +	msi_addr = (((u64)sbi_system_watchdog->wdt_attr.wdt_notif_msi_addr_high << 32 ) |
> +					sbi_system_watchdog->wdt_attr.wdt_notif_msi_addr_low);
> +	msi_data = sbi_system_watchdog->wdt_attr.wdt_notif_msi_data;
> +
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +
> +	sbi_hart_protection_temp_map_range((unsigned long)msi_addr, sizeof(u32));
> +	/* Write the MSI data to the MSI address*/
> +	writel(msi_data, (void *)(unsigned long)msi_addr);
> +	sbi_hart_protection_temp_unmap_range((unsigned long)msi_addr, sizeof(u32));
> +}
> +
> +static void sbi_watchdog_event_cleanup(struct sbi_timer_event *ev)
> +{
> +	/* Nothing to do */
> +}
> +
> +static void sbi_watchdog_expired_callback(struct sbi_timer_event *ev,
> +					  struct sbi_timer_event_restart *restart)
> +{
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +	sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_EXPIRED;
> +	/* Trigger the system reboot*/
> +	sbi_system_reset(SBI_SRST_RESET_TYPE_WARM_REBOOT, SBI_SRST_RESET_REASON_NONE);
> +
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +}
> +
> +static void sbi_watchdog_enable_timer_events()
> +{
This function is always called with wdt_lock held and it calls sbi_timer_event_start(), which takes the timer
event-list lock. In the following remote but possible scenario:

Hart 0: sbi_watchdog_pat()
           holds wdt_lock
           calls sbi_timer_event_start()
           waits for Hart 1's event_list_lock

 Hart 1: sbi_timer_process()
           holds event_list_lock
           invokes watchdog callback
           waits for wdt_lock

A deadlock is possible.

> +	u64 timeout, pretimeout;
> +	u32 pretimeout_us;
> +
> +	/* Restart the pretimeout event only if the wdt_notif_time is non zero*/
> +	if (sbi_system_watchdog->wdt_attr.wdt_notif_time != 0) {
> +		pretimeout_us = sbi_system_watchdog->wdt_attr.wdt_period -
> +				sbi_system_watchdog->wdt_attr.wdt_notif_time;
When writing SBI_WDT_NOTIF_TIME, its value is checked against the current SBI_WDT_PERIOD
but when writing SBI_WDT_PERIOD, the check of the new value is against wdt_min_period.
It is not checked whether the new period is still greater than the already configured wdt_notif_time.
So, it is possible that wdt_period - wdt_notif_time underflows. Am I missing something?

> +		pretimeout = sbi_timer_value() + sbi_timer_compute_udelta(pretimeout_us);
> +
> +		sbi_timer_event_start(&sbi_system_watchdog->wdt_pretimeout_ev, pretimeout);
> +	}
> +
> +	/* Restart the Watchdog timeout event only if the wdt_period is non zero*/
> +	if (sbi_system_watchdog->wdt_attr.wdt_period != 0) {
> +		timeout = sbi_timer_value() +
> +			  sbi_timer_compute_udelta(sbi_system_watchdog->wdt_attr.wdt_period);
> +		sbi_timer_event_start(&sbi_system_watchdog->wdt_timer_ev, timeout);
> +	}
> +}
> +
> +int sbi_watchdog_start(void)
> +{
> +	int ret;
> +
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +	/* Return error if the watchdog is not in SBI_WDT_STOPPED state*/
> +	if (sbi_system_watchdog->wdt_attr.wdt_state != SBI_WDT_STOPPED) {
> +		ret = SBI_ERR_INVALID_STATE;
> +		goto out;
> +	}
> +
> +	sbi_watchdog_enable_timer_events();
> +
> +	sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_RUNNING;
> +	ret = SBI_SUCCESS;
> +
> +out:
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +	return ret;
> +}
> +
> +int sbi_watchdog_stop(void)
> +{
> +	int ret;
> +
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +	/* Return error if the watchdog is already in SBI_WDT_STOPPED state */
> +	if (sbi_system_watchdog->wdt_attr.wdt_state == SBI_WDT_STOPPED) {
> +		ret = SBI_ERR_INVALID_STATE;
> +		goto out;
> +	}
> +
> +	/* Stop both the pretimeout and expiry events */
> +	sbi_timer_event_stop(&sbi_system_watchdog->wdt_pretimeout_ev);
> +	sbi_timer_event_stop(&sbi_system_watchdog->wdt_timer_ev);
> +
> +	sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_STOPPED;
> +	sbi_system_watchdog->wdt_attr.wdt_time_left = 0;
> +
> +	ret = SBI_SUCCESS;
> +
> +out:
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +	return ret;
> +}
> +
> +int sbi_watchdog_pat(void)
> +{
> +	int ret;
> +
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +	/* Return error if the watchdog is not in SBI_WDT_RUNNING state*/
> +	if (sbi_system_watchdog->wdt_attr.wdt_state != SBI_WDT_RUNNING) {
> +		ret = SBI_ERR_INVALID_STATE;
> +		goto out;
> +	}
> +
> +	sbi_watchdog_enable_timer_events();
> +	ret = SBI_SUCCESS;
> +
> +out:
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +	return ret;
> +}
> +
> +static void sbi_watchdog_init_attributes(void)
> +{
> +	const struct sbi_timer_device *tdev;
> +	unsigned long timer_freq;
> +	u32 capability = 0;
> +
> +	spin_lock(&sbi_system_watchdog->wdt_lock);
> +
> +	sbi_memset(&sbi_system_watchdog->wdt_attr, 0, sizeof(struct sbi_watchdog_attrs));
> +
> +	/* Retrieve the MSI capability from irqchip */
> +	if (sbi_irqchip_find_device_by_caps(SBI_IRQCHIP_CAPS_MSI, NULL))
> +		capability = CAP_ENABLE(capability, WDT_CAP_MSI_MASK);
> +
> +	sbi_system_watchdog->wdt_attr.wdt_capability = capability;
> +
> +	sbi_system_watchdog->wdt_attr.wdt_state = SBI_WDT_STOPPED;
> +
> +	/* Set the min period based on the timer frequency */
> +	tdev = sbi_timer_get_device();
> +	if (tdev != NULL) {
> +		timer_freq = tdev->timer_freq;
> +		/* Ceil division to ensure the result is non-zero */
> +		sbi_system_watchdog->wdt_attr.wdt_min_period =
> +					(u32)((SEC_TO_MICROSEC + timer_freq - 1) / timer_freq);
> +	}
> +
> +	spin_unlock(&sbi_system_watchdog->wdt_lock);
> +}
> +
> +int sbi_watchdog_init(void)
> +{
> +	/* Allocate memory for global watchdog structure sbi_system_watchdog */
> +	sbi_system_watchdog = (struct sbi_watchdog*)sbi_zalloc(sizeof(struct sbi_watchdog));
> +
> +	if(!sbi_system_watchdog) {
> +		return SBI_ENOMEM;
> +	}
> +
> +	SPIN_LOCK_INIT(sbi_system_watchdog->wdt_lock);
> +	SBI_INIT_TIMER_EVENT(&sbi_system_watchdog->wdt_timer_ev,
> +			     sbi_watchdog_expired_callback,
> +			     sbi_watchdog_event_cleanup, NULL);
> +	SBI_INIT_TIMER_EVENT(&sbi_system_watchdog->wdt_pretimeout_ev,
> +			     sbi_watchdog_pretimeout_callback,
> +			     sbi_watchdog_pretimeout_cleanup, NULL);
> +
> +	/* Initialize the default watchdog attributes */
> +	sbi_watchdog_init_attributes();
> +
> +	return SBI_SUCCESS;
> +}
> +
> +int sbi_watchdog_exit(void)
> +{
> +	/* Clean up the global watchdog */
> +	sbi_free(sbi_system_watchdog);
> +
> +	return 0;
> +}
> -- 
> 2.43.0
> 
> 
> -- 
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

-- 
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-10-23  5:02 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-02  8:30 [PATCH 0/4] RISC-V SBI watchdog support Prajwal N
2026-10-02  8:30 ` [PATCH 1/4] lib: sbi: Add timer tick to time conversion helper Prajwal N
2026-10-02  8:30 ` [PATCH 2/4] include: sbi: Add SBI watchdog extension definitions Prajwal N
2026-10-02  8:30 ` [PATCH 3/4] lib: sbi: Add SBI watchdog framework Prajwal N
2026-10-05  3:33   ` Rahul Pathak
2026-10-05  9:16   ` Rahul Pathak
2026-10-23  4:55   ` Himanshu Chauhan
2026-10-02  8:30 ` [PATCH 4/4] lib: sbi: Add ecall handler for SBI watchdog Prajwal N

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox