[PATCH 2/5] acpi: add API to build WDAT instructions

Igor Mammedov posted 5 patches 2 weeks, 1 day ago
Maintainers: "Michael S. Tsirkin" <mst@redhat.com>, Igor Mammedov <imammedo@redhat.com>, Ani Sinha <anisinha@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Paolo Bonzini <pbonzini@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, Eduardo Habkost <eduardo@habkost.net>
[PATCH 2/5] acpi: add API to build WDAT instructions
Posted by Igor Mammedov 2 weeks, 1 day ago
Add definitions for WDAT[1] actions/instructions
and build_append_wdat_ins() API to build table entries.

1)
"Hardware Watchdog Timers Design Specification"
  https://uefi.org/acpi 'Watchdog Action Table (WDAT)'

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 include/hw/acpi/wdat.h | 118 +++++++++++++++++++++++++++++++++++++++++
 hw/acpi/aml-build.c    |  14 +++++
 2 files changed, 132 insertions(+)
 create mode 100644 include/hw/acpi/wdat.h

diff --git a/include/hw/acpi/wdat.h b/include/hw/acpi/wdat.h
new file mode 100644
index 0000000000..c539e97e9b
--- /dev/null
+++ b/include/hw/acpi/wdat.h
@@ -0,0 +1,118 @@
+/*
+ * Watchdog Action Table (WDAT) definitions
+ *
+ * Copyright Red Hat, Inc. 2025
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef QEMU_HW_ACPI_WDAT_H
+#define QEMU_HW_ACPI_WDAT_H
+
+#include "hw/acpi/acpi-defs.h"
+
+/*
+ * Watchdog actions as described in
+ *  "Hardware Watchdog Timers Design Specification"
+ * for link to spec see https://uefi.org/acpi
+ *     'Watchdog Action Table (WDAT)'
+ */
+typedef enum {
+    /*
+     * Restarts the watchdog timer's countdown. This action is
+     * required.
+     */
+    WDAT_ACTION_RESET = 0x1,
+    /*
+     * Returns the current countdown value of the watchdog hardware
+     * (in count intervals).
+     */
+    WDAT_ACTION_QUERY_CURRENT_COUNTDOWN_PERIOD = 0x4,
+    /*
+     * Returns the countdown value the watchdog hardware is
+     * configured to use when reset (in count intervals).
+     */
+    WDAT_ACTION_QUERY_COUNTDOWN_PERIOD = 0x5,
+    /*
+     * Sets the countdown value (in count intervals) to be used when
+     * the watchdog timer is reset. This action is required if
+     * WDAT_ACTION_RESET does not explicitly write a new
+     * countdown value to a register during a reset. Otherwise, this
+     * action is optional.
+     */
+    WDAT_ACTION_SET_COUNTDOWN_PERIOD = 0x6,
+    /*
+     * Determines if the watchdog hardware is currently in enabled/
+     * running state. The same result must occur when performed from
+     * both from enabled/stopped state and enabled/running state. If
+     * the watchdog hardware is disabled, results are indeterminate.
+     * This action is required.
+     */
+    WDAT_ACTION_QUERY_RUNNING_STATE = 0x8,
+    /*
+     * Starts the watchdog, if not already in running state. If the
+     * watchdog hardware is disabled, results are indeterminate.
+     * This action is required.
+     */
+    WDAT_ACTION_SET_RUNNING_STATE = 0x9,
+    /*
+     * Determines if the watchdog hardware is currently in enabled/
+     * stopped state. The same result must occur when performed from
+     * both the enabled/stopped state and enabled/running state. If
+     * the watchdog hardware is disabled, results are indeterminate.
+     * This action is required.
+     */
+    WDAT_ACTION_QUERY_STOPPED_STATE = 0xA,
+    /*
+     * Stops the watchdog, if not already in stopped state. If the
+     * watchdog hardware is disabled, results are indeterminate.
+     * This action is required.
+     */
+    WDAT_ACTION_SET_STOPPED_STATE = 0xB,
+    /*
+     * Determines if the watchdog hardware is configured to perform a
+     * reboot when the watchdog is fired.
+     */
+    WDAT_ACTION_QUERY_REBOOT = 0x10,
+    /*
+     * Configures the watchdog hardware to perform a reboot when it
+     * is fired.
+     */
+    WDAT_ACTION_SET_REBOOT = 0x11,
+    /*
+     * Determines if the watchdog hardware is configured to perform a
+     * system shutdown when fired.
+     */
+    WDAT_ACTION_QUERY_SHUTDOWN = 0x12,
+    /*
+     * Configures the watchdog hardware to perform a system shutdown
+     * when fired.
+     */
+    WDAT_ACTION_SET_SHUTDOWN = 0x13,
+    /*
+     * Determines if the current boot was caused by the watchdog
+     * firing. The boot status is required to be set if the watchdog
+     * fired and caused a reboot. It is recommended that the
+     * Watchdog Status be set if the watchdog fired and caused a
+     * shutdown. This action is required.
+     */
+    WDAT_ACTION_QUERY_WATCHDOG_STATUS = 0x20,
+    /*
+     * Sets the watchdog's boot status to the default value. This
+     * action is required.
+     */
+    WDAT_ACTION_SET_WATCHDOG_STATUS = 0x21,
+} WDATAction;
+
+#define WDAT_INS_READ_VALUE 0x0
+#define WDAT_INS_READ_COUNTDOWN 0x1
+#define WDAT_INS_WRITE_VALUE 0x2
+#define WDAT_INS_WRITE_COUNTDOWN 0x3
+#define WDAT_INS_PRESERVE_REGISTER 0x80
+
+void build_append_wdat_ins(GArray *table_data,
+                           WDATAction action, uint8_t flags,
+                           struct AcpiGenericAddress as,
+                           uint32_t val, uint32_t mask);
+
+#endif /* QEMU_HW_ACPI_WDAT_H */
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2d5826a8f1..acc655df6f 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -31,6 +31,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/cutils.h"
+#include "hw/acpi/wdat.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -2639,3 +2640,16 @@ Aml *aml_error_device(void)
 
     return dev;
 }
+
+void build_append_wdat_ins(GArray *table_data,
+                           WDATAction action, uint8_t flags,
+                           struct AcpiGenericAddress as,
+                           uint32_t val, uint32_t mask)
+{
+    build_append_int_noprefix(table_data, action, 1);    /* Watchdog Action */
+    build_append_int_noprefix(table_data, flags, 1);     /* Instruction Flags */
+    build_append_int_noprefix(table_data, 0, 2);         /* Reserved */
+    build_append_gas_from_struct(table_data, &as);       /* Register Region */
+    build_append_int_noprefix(table_data, val, 4);       /* Value */
+    build_append_int_noprefix(table_data, mask, 4);      /* Mask */
+}
-- 
2.47.3