* [PATCH v2 01/21] acpi: add API to build WDAT instructions
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-13 15:23 ` Zhao Liu
2026-05-26 14:11 ` Eric Auger
2026-03-03 9:25 ` [PATCH v2 02/21] x86: q35: add 'wdat' property Igor Mammedov
` (21 subsequent siblings)
22 siblings, 2 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
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>
Reviewed-by: Ani Sinha <anisinha@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..89803eef4b
--- /dev/null
+++ b/include/hw/acpi/wdat.h
@@ -0,0 +1,118 @@
+/*
+ * Watchdog Action Table (WDAT) definitions
+ *
+ * Copyright Red Hat, Inc. 2026
+ * 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 ea1c415b21..9f9ce28dcc 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -32,6 +32,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)
{
@@ -2647,3 +2648,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
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 01/21] acpi: add API to build WDAT instructions
2026-03-03 9:25 ` [PATCH v2 01/21] acpi: add API to build WDAT instructions Igor Mammedov
@ 2026-05-13 15:23 ` Zhao Liu
2026-05-26 14:11 ` Eric Auger
1 sibling, 0 replies; 57+ messages in thread
From: Zhao Liu @ 2026-05-13 15:23 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
On Tue, Mar 03, 2026 at 10:25:12AM +0100, Igor Mammedov wrote:
> Date: Tue, 3 Mar 2026 10:25:12 +0100
> From: Igor Mammedov <imammedo@redhat.com>
> Subject: [PATCH v2 01/21] acpi: add API to build WDAT instructions
>
> 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>
> Reviewed-by: Ani Sinha <anisinha@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
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v2 01/21] acpi: add API to build WDAT instructions
2026-03-03 9:25 ` [PATCH v2 01/21] acpi: add API to build WDAT instructions Igor Mammedov
2026-05-13 15:23 ` Zhao Liu
@ 2026-05-26 14:11 ` Eric Auger
1 sibling, 0 replies; 57+ messages in thread
From: Eric Auger @ 2026-05-26 14:11 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> 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>
> Reviewed-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> 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..89803eef4b
> --- /dev/null
> +++ b/include/hw/acpi/wdat.h
> @@ -0,0 +1,118 @@
> +/*
> + * Watchdog Action Table (WDAT) definitions
> + *
> + * Copyright Red Hat, Inc. 2026
> + * 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 ea1c415b21..9f9ce28dcc 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -32,6 +32,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)
> {
> @@ -2647,3 +2648,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 */
> +}
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 02/21] x86: q35: add 'wdat' property
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 01/21] acpi: add API to build WDAT instructions Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-13 14:58 ` Zhao Liu
2026-03-03 9:25 ` [PATCH v2 03/21] x86: q35: generate WDAT ACPI table Igor Mammedov
` (20 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Used for enabling WDAT based watchdog for builtin iTCO watchdog.
Usage:
-M q35,wdat={on|off}
By default it is disabled.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
include/hw/i386/pc.h | 1 +
hw/i386/pc_q35.c | 18 ++++++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 1cf88c1697..8e34e57be3 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -45,6 +45,7 @@ typedef struct PCMachineState {
const char *south_bridge;
bool acpi_build_enabled;
+ bool wdat_enabled;
bool smbus_enabled;
bool sata_enabled;
bool hpet_enabled;
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 9158631f76..49f89544f3 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -330,6 +330,18 @@ static void pc_q35_init(MachineState *machine)
}
}
+static bool pc_q35_machine_get_wdat(Object *o, Error **errp)
+{
+ PCMachineState *pcms = PC_MACHINE(o);
+ return pcms->wdat_enabled;
+}
+
+static void pc_q35_machine_set_wdat(Object *o, bool value, Error **errp)
+{
+ PCMachineState *pcms = PC_MACHINE(o);
+ pcms->wdat_enabled = value;
+}
+
#define DEFINE_Q35_MACHINE(major, minor) \
DEFINE_PC_VER_MACHINE(pc_q35, "pc-q35", pc_q35_init, false, NULL, major, minor);
@@ -342,6 +354,7 @@ static void pc_q35_init(MachineState *machine)
static void pc_q35_machine_options(MachineClass *m)
{
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
+ ObjectClass *oc = OBJECT_CLASS(m);
pcmc->pci_root_uid = 0;
pcmc->default_cpu_version = 1;
@@ -360,6 +373,11 @@ static void pc_q35_machine_options(MachineClass *m)
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
machine_class_allow_dynamic_sysbus_dev(m, TYPE_UEFI_VARS_X64);
+ object_class_property_add_bool(oc, "wdat",
+ pc_q35_machine_get_wdat, pc_q35_machine_set_wdat);
+ object_class_property_set_description(oc, "wdat",
+ "Enable WDAT watchdog support. Default: off");
+
compat_props_add(m->compat_props,
pc_q35_compat_defaults, pc_q35_compat_defaults_len);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 02/21] x86: q35: add 'wdat' property
2026-03-03 9:25 ` [PATCH v2 02/21] x86: q35: add 'wdat' property Igor Mammedov
@ 2026-05-13 14:58 ` Zhao Liu
2026-05-14 7:16 ` Ani Sinha
0 siblings, 1 reply; 57+ messages in thread
From: Zhao Liu @ 2026-05-13 14:58 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
On Tue, Mar 03, 2026 at 10:25:13AM +0100, Igor Mammedov wrote:
> Date: Tue, 3 Mar 2026 10:25:13 +0100
> From: Igor Mammedov <imammedo@redhat.com>
> Subject: [PATCH v2 02/21] x86: q35: add 'wdat' property
>
> Used for enabling WDAT based watchdog for builtin iTCO watchdog.
> Usage:
> -M q35,wdat={on|off}
> By default it is disabled.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> include/hw/i386/pc.h | 1 +
> hw/i386/pc_q35.c | 18 ++++++++++++++++++
> 2 files changed, 19 insertions(+)
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 02/21] x86: q35: add 'wdat' property
2026-05-13 14:58 ` Zhao Liu
@ 2026-05-14 7:16 ` Ani Sinha
0 siblings, 0 replies; 57+ messages in thread
From: Ani Sinha @ 2026-05-14 7:16 UTC (permalink / raw)
To: Zhao Liu
Cc: Igor Mammedov, qemu-devel, mst, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
> On 13 May 2026, at 8:28 PM, Zhao Liu <zhao1.liu@intel.com> wrote:
>
> On Tue, Mar 03, 2026 at 10:25:13AM +0100, Igor Mammedov wrote:
>> Date: Tue, 3 Mar 2026 10:25:13 +0100
>> From: Igor Mammedov <imammedo@redhat.com>
>> Subject: [PATCH v2 02/21] x86: q35: add 'wdat' property
>>
>> Used for enabling WDAT based watchdog for builtin iTCO watchdog.
>> Usage:
>> -M q35,wdat={on|off}
>> By default it is disabled.
>>
>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>> ---
>> include/hw/i386/pc.h | 1 +
>> hw/i386/pc_q35.c | 18 ++++++++++++++++++
>> 2 files changed, 19 insertions(+)
>
> Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 03/21] x86: q35: generate WDAT ACPI table
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 01/21] acpi: add API to build WDAT instructions Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 02/21] x86: q35: add 'wdat' property Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-13 15:47 ` Zhao Liu
2026-03-03 9:25 ` [PATCH v2 04/21] tests: acpi: x86/q35: whitelist new WDAT table Igor Mammedov
` (19 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
It will generate WDAT table [1] customized for TCO watchdog.
This allows Windows guests (Windows Server 2008/Vista+) to
use TCO watchdog using built-in generic driver, which
alleviates need to install vendor specific drivers.
Given that enabling it might change guest behaviour
(both Windows/Linux) the feature is disabled by default.
Users that need it can enable the feature with
following CLI option.
-machine wdat=on
1)
"Hardware Watchdog Timers Design Specification"
https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
---
include/hw/acpi/wdat-ich9.h | 15 +++++++
hw/acpi/meson.build | 3 +-
hw/acpi/wdat-ich9-stub.c | 15 +++++++
hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++++++++++++++++++++
hw/i386/acpi-build.c | 12 +++++
5 files changed, 134 insertions(+), 1 deletion(-)
create mode 100644 include/hw/acpi/wdat-ich9.h
create mode 100644 hw/acpi/wdat-ich9-stub.c
create mode 100644 hw/acpi/wdat-ich9.c
diff --git a/include/hw/acpi/wdat-ich9.h b/include/hw/acpi/wdat-ich9.h
new file mode 100644
index 0000000000..60a2a6a112
--- /dev/null
+++ b/include/hw/acpi/wdat-ich9.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef QEMU_HW_ACPI_WDAT_ICH9_H
+#define QEMU_HW_ACPI_WDAT_ICH9_H
+
+#include "hw/acpi/aml-build.h"
+
+void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+ const char *oem_table_id, uint64_t tco_base);
+
+#endif /* QEMU_HW_ACPI_WDAT_ICH9_H */
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
index 66c978aae8..22290ca835 100644
--- a/hw/acpi/meson.build
+++ b/hw/acpi/meson.build
@@ -24,7 +24,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_true: files('pci-bridge.c'))
acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_true: files('pcihp.c'))
acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_false: files('acpi-pci-hotplug-stub.c'))
acpi_ss.add(when: 'CONFIG_ACPI_VIOT', if_true: files('viot.c'))
-acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c', 'ich9_timer.c'))
+acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c', 'ich9_timer.c', 'wdat-ich9.c'))
acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c'))
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
@@ -33,6 +33,7 @@ if have_tpm
endif
system_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c'))
system_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_false: files('pci-bridge-stub.c'))
+system_ss.add(when: 'CONFIG_ACPI_ICH9', if_false: files('wdat-ich9-stub.c'))
system_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
system_ss.add(when: 'CONFIG_GHES_CPER', if_true: files('ghes_cper.c'))
system_ss.add(when: 'CONFIG_GHES_CPER', if_false: files('ghes_cper_stub.c'))
diff --git a/hw/acpi/wdat-ich9-stub.c b/hw/acpi/wdat-ich9-stub.c
new file mode 100644
index 0000000000..7c30ef3558
--- /dev/null
+++ b/hw/acpi/wdat-ich9-stub.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/wdat-ich9.h"
+
+void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+ const char *oem_table_id, uint64_t tco_base)
+{
+ g_assert_not_reached();
+}
diff --git a/hw/acpi/wdat-ich9.c b/hw/acpi/wdat-ich9.c
new file mode 100644
index 0000000000..259c45c62d
--- /dev/null
+++ b/hw/acpi/wdat-ich9.c
@@ -0,0 +1,90 @@
+/*
+ * TCO Watchdog Action Table (WDAT)
+ *
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/wdat.h"
+#include "hw/acpi/wdat-ich9.h"
+#include "hw/southbridge/ich9.h"
+
+#define TCO_REG(base, reg_offset, reg_width) { .space_id = AML_AS_SYSTEM_IO, \
+ .address = base + reg_offset, .bit_width = reg_width, \
+ .access_width = AML_WORD_ACC, };
+
+/*
+ * "Hardware Watchdog Timers Design Specification"
+ * https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
+ *
+ * ICH9 specific implementation.
+ */
+void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+ const char *oem_table_id, uint64_t tco_base)
+{
+ AcpiTable table = { .sig = "WDAT", .rev = 1, .oem_id = oem_id,
+ .oem_table_id = oem_table_id };
+ struct AcpiGenericAddress tco_rld = TCO_REG(tco_base, 0x0, 16);
+ struct AcpiGenericAddress tco2_sts = TCO_REG(tco_base, 0x6, 16);
+ struct AcpiGenericAddress tco1_cnt = TCO_REG(tco_base, 0x8, 16);
+ struct AcpiGenericAddress tco_tmr = TCO_REG(tco_base, 0x12, 16);
+
+ acpi_table_begin(&table, table_data);
+ build_append_int_noprefix(table_data, 0x20, 4); /* Watchdog Header Length */
+ build_append_int_noprefix(table_data, 0xff, 2); /* PCI Segment */
+ build_append_int_noprefix(table_data, 0xff, 1); /* PCI Bus Number */
+ build_append_int_noprefix(table_data, 0xff, 1); /* PCI Device Number */
+ build_append_int_noprefix(table_data, 0xff, 1); /* PCI Function Number */
+ build_append_int_noprefix(table_data, 0, 3); /* Reserved */
+ /*
+ * limits/resolution are defined by ICH9 TCO spec
+ */
+ build_append_int_noprefix(table_data, 0x258, 4);/* Timer Period, ms */
+ build_append_int_noprefix(table_data, 0x3ff, 4);/* Maximum Count */
+ build_append_int_noprefix(table_data, 0x4, 4); /* Minimum Count */
+ /*
+ * WATCHDOG_ENABLED & WATCHDOG_STOPPED_IN_SLEEP_STATE
+ */
+ build_append_int_noprefix(table_data, 0x81, 1); /* Watchdog Flags */
+ build_append_int_noprefix(table_data, 0, 3); /* Reserved */
+ /*
+ * watchdog instruction entries
+ */
+ build_append_int_noprefix(table_data, 10 /* # of actions below */, 4);
+ /* Action table */
+ build_append_wdat_ins(table_data, WDAT_ACTION_RESET,
+ WDAT_INS_WRITE_VALUE,
+ tco_rld, 0x1, 0x1ff);
+ build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_RUNNING_STATE,
+ WDAT_INS_READ_VALUE,
+ tco1_cnt, 0x0, 0x800);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_RUNNING_STATE,
+ WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+ tco1_cnt, 0, 0x800);
+ build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_STOPPED_STATE,
+ WDAT_INS_READ_VALUE,
+ tco1_cnt, 0x800, 0x800);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_STOPPED_STATE,
+ WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+ tco1_cnt, 0x800, 0x800);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_COUNTDOWN_PERIOD,
+ WDAT_INS_WRITE_COUNTDOWN,
+ tco_tmr, 0x0, 0x3FF);
+ build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_COUNTDOWN_PERIOD,
+ WDAT_INS_READ_COUNTDOWN,
+ tco_tmr, 0x0, 0x3FF);
+ build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_WATCHDOG_STATUS,
+ WDAT_INS_READ_VALUE,
+ tco2_sts, 0x2, 0x2);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_WATCHDOG_STATUS,
+ WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+ tco2_sts, 0x2, 0x2);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_WATCHDOG_STATUS,
+ WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+ tco2_sts, 0x4, 0x4);
+
+ acpi_table_end(linker, &table);
+}
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index f622b91b76..b623926de4 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -78,6 +78,7 @@
#include "hw/acpi/hmat.h"
#include "hw/acpi/viot.h"
+#include "hw/acpi/wdat-ich9.h"
#include CONFIG_DEVICES
@@ -110,6 +111,7 @@ typedef struct AcpiPmInfo {
uint16_t cpu_hp_io_base;
uint16_t pcihp_io_base;
uint16_t pcihp_io_len;
+ uint64_t tco_io_base;
} AcpiPmInfo;
typedef struct AcpiMiscInfo {
@@ -204,6 +206,7 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm)
pm->pcihp_io_len = 0;
pm->smi_on_cpuhp = false;
pm->smi_on_cpu_unplug = false;
+ pm->tco_io_base = 0;
assert(obj);
init_common_fadt_data(machine, obj, &pm->fadt);
@@ -225,6 +228,8 @@ static void acpi_get_pm_info(MachineState *machine, AcpiPmInfo *pm)
!!(smi_features & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT));
pm->smi_on_cpu_unplug =
!!(smi_features & BIT_ULL(ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT));
+ pm->tco_io_base = object_property_get_uint(obj, ACPI_PM_PROP_PM_IO_BASE,
+ NULL) + ICH9_PMIO_TCO_RLD;
}
pm->pcihp_io_base =
object_property_get_uint(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
@@ -2078,6 +2083,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
acpi_add_table(table_offsets, tables_blob);
build_waet(tables_blob, tables->linker, x86ms->oem_id, x86ms->oem_table_id);
+ if (pcms->wdat_enabled == true) {
+ g_assert(pm.tco_io_base);
+ acpi_add_table(table_offsets, tables_blob);
+ build_ich9_wdat(tables_blob, tables->linker, x86ms->oem_id,
+ x86ms->oem_table_id, pm.tco_io_base);
+ }
+
/* Add tables supplied by user (if any) */
for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
unsigned len = acpi_table_len(u);
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 03/21] x86: q35: generate WDAT ACPI table
2026-03-03 9:25 ` [PATCH v2 03/21] x86: q35: generate WDAT ACPI table Igor Mammedov
@ 2026-05-13 15:47 ` Zhao Liu
2026-05-13 15:28 ` Michael S. Tsirkin
0 siblings, 1 reply; 57+ messages in thread
From: Zhao Liu @ 2026-05-13 15:47 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
On Tue, Mar 03, 2026 at 10:25:14AM +0100, Igor Mammedov wrote:
> Date: Tue, 3 Mar 2026 10:25:14 +0100
> From: Igor Mammedov <imammedo@redhat.com>
> Subject: [PATCH v2 03/21] x86: q35: generate WDAT ACPI table
>
> It will generate WDAT table [1] customized for TCO watchdog.
> This allows Windows guests (Windows Server 2008/Vista+) to
> use TCO watchdog using built-in generic driver, which
> alleviates need to install vendor specific drivers.
>
> Given that enabling it might change guest behaviour
> (both Windows/Linux) the feature is disabled by default.
>
> Users that need it can enable the feature with
> following CLI option.
> -machine wdat=on
>
> 1)
> "Hardware Watchdog Timers Design Specification"
> https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Reviewed-by: Ani Sinha <anisinha@redhat.com>
> ---
> include/hw/acpi/wdat-ich9.h | 15 +++++++
> hw/acpi/meson.build | 3 +-
> hw/acpi/wdat-ich9-stub.c | 15 +++++++
> hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++++++++++++++++++++
> hw/i386/acpi-build.c | 12 +++++
> 5 files changed, 134 insertions(+), 1 deletion(-)
> create mode 100644 include/hw/acpi/wdat-ich9.h
> create mode 100644 hw/acpi/wdat-ich9-stub.c
> create mode 100644 hw/acpi/wdat-ich9.c
...
> +void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
> + const char *oem_table_id, uint64_t tco_base)
> +{
> + AcpiTable table = { .sig = "WDAT", .rev = 1, .oem_id = oem_id,
> + .oem_table_id = oem_table_id };
> + struct AcpiGenericAddress tco_rld = TCO_REG(tco_base, 0x0, 16);
> + struct AcpiGenericAddress tco2_sts = TCO_REG(tco_base, 0x6, 16);
> + struct AcpiGenericAddress tco1_cnt = TCO_REG(tco_base, 0x8, 16);
> + struct AcpiGenericAddress tco_tmr = TCO_REG(tco_base, 0x12, 16);
> +
> + acpi_table_begin(&table, table_data);
> + build_append_int_noprefix(table_data, 0x20, 4); /* Watchdog Header Length */
> + build_append_int_noprefix(table_data, 0xff, 2); /* PCI Segment */
> + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Bus Number */
> + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Device Number */
> + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Function Number */
> + build_append_int_noprefix(table_data, 0, 3); /* Reserved */
> + /*
> + * limits/resolution are defined by ICH9 TCO spec
> + */
> + build_append_int_noprefix(table_data, 0x258, 4);/* Timer Period, ms */
> + build_append_int_noprefix(table_data, 0x3ff, 4);/* Maximum Count */
> + build_append_int_noprefix(table_data, 0x4, 4); /* Minimum Count */
Spec said: The time-out period before the WDT fires is recommended to be at
least 5 minutes and is required to be less than 4,294,967,296 count
intervals.
Here we encode 0x4 * 0x258 = 2400ms, less than 5 minutes. But I
understand because "5 minutes" is just "recommanded" by spec, so 2400ms is
okay.
LGTM,
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 03/21] x86: q35: generate WDAT ACPI table
2026-05-13 15:47 ` Zhao Liu
@ 2026-05-13 15:28 ` Michael S. Tsirkin
2026-05-14 14:32 ` Igor Mammedov
0 siblings, 1 reply; 57+ messages in thread
From: Michael S. Tsirkin @ 2026-05-13 15:28 UTC (permalink / raw)
To: Zhao Liu
Cc: Igor Mammedov, qemu-devel, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
On Wed, May 13, 2026 at 11:47:19PM +0800, Zhao Liu wrote:
> On Tue, Mar 03, 2026 at 10:25:14AM +0100, Igor Mammedov wrote:
> > Date: Tue, 3 Mar 2026 10:25:14 +0100
> > From: Igor Mammedov <imammedo@redhat.com>
> > Subject: [PATCH v2 03/21] x86: q35: generate WDAT ACPI table
> >
> > It will generate WDAT table [1] customized for TCO watchdog.
> > This allows Windows guests (Windows Server 2008/Vista+) to
> > use TCO watchdog using built-in generic driver, which
> > alleviates need to install vendor specific drivers.
> >
> > Given that enabling it might change guest behaviour
> > (both Windows/Linux) the feature is disabled by default.
> >
> > Users that need it can enable the feature with
> > following CLI option.
> > -machine wdat=on
> >
> > 1)
> > "Hardware Watchdog Timers Design Specification"
> > https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
> >
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > Reviewed-by: Ani Sinha <anisinha@redhat.com>
> > ---
> > include/hw/acpi/wdat-ich9.h | 15 +++++++
> > hw/acpi/meson.build | 3 +-
> > hw/acpi/wdat-ich9-stub.c | 15 +++++++
> > hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++++++++++++++++++++
> > hw/i386/acpi-build.c | 12 +++++
> > 5 files changed, 134 insertions(+), 1 deletion(-)
> > create mode 100644 include/hw/acpi/wdat-ich9.h
> > create mode 100644 hw/acpi/wdat-ich9-stub.c
> > create mode 100644 hw/acpi/wdat-ich9.c
>
> ...
>
> > +void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
> > + const char *oem_table_id, uint64_t tco_base)
> > +{
> > + AcpiTable table = { .sig = "WDAT", .rev = 1, .oem_id = oem_id,
> > + .oem_table_id = oem_table_id };
> > + struct AcpiGenericAddress tco_rld = TCO_REG(tco_base, 0x0, 16);
> > + struct AcpiGenericAddress tco2_sts = TCO_REG(tco_base, 0x6, 16);
> > + struct AcpiGenericAddress tco1_cnt = TCO_REG(tco_base, 0x8, 16);
> > + struct AcpiGenericAddress tco_tmr = TCO_REG(tco_base, 0x12, 16);
> > +
> > + acpi_table_begin(&table, table_data);
> > + build_append_int_noprefix(table_data, 0x20, 4); /* Watchdog Header Length */
> > + build_append_int_noprefix(table_data, 0xff, 2); /* PCI Segment */
> > + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Bus Number */
> > + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Device Number */
> > + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Function Number */
> > + build_append_int_noprefix(table_data, 0, 3); /* Reserved */
> > + /*
> > + * limits/resolution are defined by ICH9 TCO spec
> > + */
> > + build_append_int_noprefix(table_data, 0x258, 4);/* Timer Period, ms */
> > + build_append_int_noprefix(table_data, 0x3ff, 4);/* Maximum Count */
> > + build_append_int_noprefix(table_data, 0x4, 4); /* Minimum Count */
>
> Spec said: The time-out period before the WDT fires is recommended to be at
> least 5 minutes and is required to be less than 4,294,967,296 count
> intervals.
>
> Here we encode 0x4 * 0x258 = 2400ms, less than 5 minutes. But I
> understand because "5 minutes" is just "recommanded" by spec, so 2400ms is
> okay.
>
> LGTM,
>
> Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
maybe a comment why it's shorter?
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 03/21] x86: q35: generate WDAT ACPI table
2026-05-13 15:28 ` Michael S. Tsirkin
@ 2026-05-14 14:32 ` Igor Mammedov
0 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-05-14 14:32 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Zhao Liu, qemu-devel, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
On Wed, 13 May 2026 11:28:01 -0400
"Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Wed, May 13, 2026 at 11:47:19PM +0800, Zhao Liu wrote:
> > On Tue, Mar 03, 2026 at 10:25:14AM +0100, Igor Mammedov wrote:
> > > Date: Tue, 3 Mar 2026 10:25:14 +0100
> > > From: Igor Mammedov <imammedo@redhat.com>
> > > Subject: [PATCH v2 03/21] x86: q35: generate WDAT ACPI table
> > >
> > > It will generate WDAT table [1] customized for TCO watchdog.
> > > This allows Windows guests (Windows Server 2008/Vista+) to
> > > use TCO watchdog using built-in generic driver, which
> > > alleviates need to install vendor specific drivers.
> > >
> > > Given that enabling it might change guest behaviour
> > > (both Windows/Linux) the feature is disabled by default.
> > >
> > > Users that need it can enable the feature with
> > > following CLI option.
> > > -machine wdat=on
> > >
> > > 1)
> > > "Hardware Watchdog Timers Design Specification"
> > > https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
> > >
> > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > Reviewed-by: Ani Sinha <anisinha@redhat.com>
> > > ---
> > > include/hw/acpi/wdat-ich9.h | 15 +++++++
> > > hw/acpi/meson.build | 3 +-
> > > hw/acpi/wdat-ich9-stub.c | 15 +++++++
> > > hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++++++++++++++++++++
> > > hw/i386/acpi-build.c | 12 +++++
> > > 5 files changed, 134 insertions(+), 1 deletion(-)
> > > create mode 100644 include/hw/acpi/wdat-ich9.h
> > > create mode 100644 hw/acpi/wdat-ich9-stub.c
> > > create mode 100644 hw/acpi/wdat-ich9.c
> >
> > ...
> >
> > > +void build_ich9_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
> > > + const char *oem_table_id, uint64_t tco_base)
> > > +{
> > > + AcpiTable table = { .sig = "WDAT", .rev = 1, .oem_id = oem_id,
> > > + .oem_table_id = oem_table_id };
> > > + struct AcpiGenericAddress tco_rld = TCO_REG(tco_base, 0x0, 16);
> > > + struct AcpiGenericAddress tco2_sts = TCO_REG(tco_base, 0x6, 16);
> > > + struct AcpiGenericAddress tco1_cnt = TCO_REG(tco_base, 0x8, 16);
> > > + struct AcpiGenericAddress tco_tmr = TCO_REG(tco_base, 0x12, 16);
> > > +
> > > + acpi_table_begin(&table, table_data);
> > > + build_append_int_noprefix(table_data, 0x20, 4); /* Watchdog Header Length */
> > > + build_append_int_noprefix(table_data, 0xff, 2); /* PCI Segment */
> > > + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Bus Number */
> > > + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Device Number */
> > > + build_append_int_noprefix(table_data, 0xff, 1); /* PCI Function Number */
> > > + build_append_int_noprefix(table_data, 0, 3); /* Reserved */
> > > + /*
> > > + * limits/resolution are defined by ICH9 TCO spec
> > > + */
> > > + build_append_int_noprefix(table_data, 0x258, 4);/* Timer Period, ms */
> > > + build_append_int_noprefix(table_data, 0x3ff, 4);/* Maximum Count */
> > > + build_append_int_noprefix(table_data, 0x4, 4); /* Minimum Count */
> >
> > Spec said: The time-out period before the WDT fires is recommended to be at
> > least 5 minutes and is required to be less than 4,294,967,296 count
> > intervals.
> >
> > Here we encode 0x4 * 0x258 = 2400ms, less than 5 minutes. But I
> > understand because "5 minutes" is just "recommanded" by spec, so 2400ms is
> > okay.
> >
> > LGTM,
> >
> > Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
>
>
> maybe a comment why it's shorter?
it's not shorter nor arbitrary value, comments already say it all.
and provide enough context for spec lookup:
WDAT:
/Timer Period/ Contains the period of one timer count (in milliseconds).
it's timer resolution.
iTCO spec says: "The timer is clocked at approximately 0.6 seconds"
and then MIN/MAX aren't default value either, they are limits per iTCO spec,
as comment above says. The guest OS sets actual value within declared here constrains.
So no extra comments were added (just enough for spec lookup).
But my view is obviously biased,
just say what more you'd like to see in comments and I'll post fixup.
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 04/21] tests: acpi: x86/q35: whitelist new WDAT table
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (2 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 03/21] x86: q35: generate WDAT ACPI table Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-13 15:48 ` Zhao Liu
2026-03-03 9:25 ` [PATCH v2 05/21] tests: acpi: x86/q35: add WDAT table test case Igor Mammedov
` (18 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Acked-by: Ani Sinha <anisinha@redhat.com>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 +
tests/data/acpi/x86/q35/WDAT.wdat | 0
2 files changed, 1 insertion(+)
create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..14b680debe 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,2 @@
/* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/x86/q35/WDAT.wdat",
diff --git a/tests/data/acpi/x86/q35/WDAT.wdat b/tests/data/acpi/x86/q35/WDAT.wdat
new file mode 100644
index 0000000000..e69de29bb2
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 04/21] tests: acpi: x86/q35: whitelist new WDAT table
2026-03-03 9:25 ` [PATCH v2 04/21] tests: acpi: x86/q35: whitelist new WDAT table Igor Mammedov
@ 2026-05-13 15:48 ` Zhao Liu
0 siblings, 0 replies; 57+ messages in thread
From: Zhao Liu @ 2026-05-13 15:48 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
On Tue, Mar 03, 2026 at 10:25:15AM +0100, Igor Mammedov wrote:
> Date: Tue, 3 Mar 2026 10:25:15 +0100
> From: Igor Mammedov <imammedo@redhat.com>
> Subject: [PATCH v2 04/21] tests: acpi: x86/q35: whitelist new WDAT table
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Acked-by: Ani Sinha <anisinha@redhat.com>
> ---
> tests/qtest/bios-tables-test-allowed-diff.h | 1 +
> tests/data/acpi/x86/q35/WDAT.wdat | 0
> 2 files changed, 1 insertion(+)
> create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 05/21] tests: acpi: x86/q35: add WDAT table test case
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (3 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 04/21] tests: acpi: x86/q35: whitelist new WDAT table Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-13 15:49 ` Zhao Liu
2026-03-03 9:25 ` [PATCH v2 06/21] tests: acpi: x86/q35: update expected WDAT blob Igor Mammedov
` (17 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
---
tests/qtest/bios-tables-test.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index a5a5b8807b..5b01a657e5 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -2530,6 +2530,18 @@ static void test_acpi_isapc_smbios_legacy(void)
free_test_data(&data);
}
+static void test_acpi_q35_wdat(void)
+{
+ test_data data = {
+ .machine = MACHINE_Q35,
+ .arch = "x86",
+ .variant = ".wdat",
+ };
+
+ test_acpi_one("-machine wdat=on", &data);
+ free_test_data(&data);
+}
+
static void test_oem_fields(test_data *data)
{
int i;
@@ -2824,6 +2836,7 @@ int main(int argc, char *argv[])
qtest_add_func("acpi/q35/cxl", test_acpi_q35_cxl);
#endif
qtest_add_func("acpi/q35/slic", test_acpi_q35_slic);
+ qtest_add_func("acpi/q35/wdat", test_acpi_q35_wdat);
}
if (qtest_has_machine("microvm")) {
qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 05/21] tests: acpi: x86/q35: add WDAT table test case
2026-03-03 9:25 ` [PATCH v2 05/21] tests: acpi: x86/q35: add WDAT table test case Igor Mammedov
@ 2026-05-13 15:49 ` Zhao Liu
0 siblings, 0 replies; 57+ messages in thread
From: Zhao Liu @ 2026-05-13 15:49 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
On Tue, Mar 03, 2026 at 10:25:16AM +0100, Igor Mammedov wrote:
> Date: Tue, 3 Mar 2026 10:25:16 +0100
> From: Igor Mammedov <imammedo@redhat.com>
> Subject: [PATCH v2 05/21] tests: acpi: x86/q35: add WDAT table test case
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Reviewed-by: Ani Sinha <anisinha@redhat.com>
> ---
> tests/qtest/bios-tables-test.c | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 06/21] tests: acpi: x86/q35: update expected WDAT blob
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (4 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 05/21] tests: acpi: x86/q35: add WDAT table test case Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-13 15:48 ` Zhao Liu
2026-03-03 9:25 ` [PATCH v2 07/21] arm: sbsa_gwdt: fixup default "clock-frequency" Igor Mammedov
` (16 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
replace blank table with a new one:
+[000h 0000 4] Signature : "WDAT" [Watchdog Action Table]
+[004h 0004 4] Table Length : 00000134
+[008h 0008 1] Revision : 01
+[009h 0009 1] Checksum : 31
+[00Ah 0010 6] Oem ID : "BOCHS "
+[010h 0016 8] Oem Table ID : "BXPC "
+[018h 0024 4] Oem Revision : 00000001
+[01Ch 0028 4] Asl Compiler ID : "BXPC"
+[020h 0032 4] Asl Compiler Revision : 00000001
+
+[024h 0036 4] Header Length : 00000020
+[028h 0040 2] PCI Segment : 00FF
+[02Ah 0042 1] PCI Bus : FF
+[02Bh 0043 1] PCI Device : FF
+[02Ch 0044 1] PCI Function : FF
+[02Dh 0045 3] Reserved : 000000
+[030h 0048 4] Timer Period : 00000258
+[034h 0052 4] Max Count : 000003FF
+[038h 0056 4] Min Count : 00000004
+[03Ch 0060 1] Flags (decoded below) : 81
+ Enabled : 1
+ Stopped When Asleep : 1
+[03Dh 0061 3] Reserved : 000000
+[040h 0064 4] Watchdog Entry Count : 0000000A
+
+[044h 0068 1] Watchdog Action : 01
+[045h 0069 1] Instruction : 02
+[046h 0070 2] Reserved : 0000
+
+[048h 0072 12] Register Region : [Generic Address Structure]
+[048h 0072 1] Space ID : 01 [SystemIO]
+[049h 0073 1] Bit Width : 10
+[04Ah 0074 1] Bit Offset : 00
+[04Bh 0075 1] Encoded Access Width : 02 [Word Access:16]
+[04Ch 0076 8] Address : 0000000000000660
+
+[054h 0084 4] Value : 00000001
+[058h 0088 4] Register Mask : 000001FF
+
+[05Ch 0092 1] Watchdog Action : 08
+[05Dh 0093 1] Instruction : 00
+[05Eh 0094 2] Reserved : 0000
+
+[060h 0096 12] Register Region : [Generic Address Structure]
+[060h 0096 1] Space ID : 01 [SystemIO]
+[061h 0097 1] Bit Width : 10
+[062h 0098 1] Bit Offset : 00
+[063h 0099 1] Encoded Access Width : 02 [Word Access:16]
+[064h 0100 8] Address : 0000000000000668
+
+[06Ch 0108 4] Value : 00000000
+[070h 0112 4] Register Mask : 00000800
+
+[074h 0116 1] Watchdog Action : 09
+[075h 0117 1] Instruction : 82
+[076h 0118 2] Reserved : 0000
+
+[078h 0120 12] Register Region : [Generic Address Structure]
+[078h 0120 1] Space ID : 01 [SystemIO]
+[079h 0121 1] Bit Width : 10
+[07Ah 0122 1] Bit Offset : 00
+[07Bh 0123 1] Encoded Access Width : 02 [Word Access:16]
+[07Ch 0124 8] Address : 0000000000000668
+
+[084h 0132 4] Value : 00000000
+[088h 0136 4] Register Mask : 00000800
+
+[08Ch 0140 1] Watchdog Action : 0A
+[08Dh 0141 1] Instruction : 00
+[08Eh 0142 2] Reserved : 0000
+
+[090h 0144 12] Register Region : [Generic Address Structure]
+[090h 0144 1] Space ID : 01 [SystemIO]
+[091h 0145 1] Bit Width : 10
+[092h 0146 1] Bit Offset : 00
+[093h 0147 1] Encoded Access Width : 02 [Word Access:16]
+[094h 0148 8] Address : 0000000000000668
+
+[09Ch 0156 4] Value : 00000800
+[0A0h 0160 4] Register Mask : 00000800
+
+[0A4h 0164 1] Watchdog Action : 0B
+[0A5h 0165 1] Instruction : 82
+[0A6h 0166 2] Reserved : 0000
+
+[0A8h 0168 12] Register Region : [Generic Address Structure]
+[0A8h 0168 1] Space ID : 01 [SystemIO]
+[0A9h 0169 1] Bit Width : 10
+[0AAh 0170 1] Bit Offset : 00
+[0ABh 0171 1] Encoded Access Width : 02 [Word Access:16]
+[0ACh 0172 8] Address : 0000000000000668
+
+[0B4h 0180 4] Value : 00000800
+[0B8h 0184 4] Register Mask : 00000800
+
+[0BCh 0188 1] Watchdog Action : 06
+[0BDh 0189 1] Instruction : 03
+[0BEh 0190 2] Reserved : 0000
+
+[0C0h 0192 12] Register Region : [Generic Address Structure]
+[0C0h 0192 1] Space ID : 01 [SystemIO]
+[0C1h 0193 1] Bit Width : 10
+[0C2h 0194 1] Bit Offset : 00
+[0C3h 0195 1] Encoded Access Width : 02 [Word Access:16]
+[0C4h 0196 8] Address : 0000000000000672
+
+[0CCh 0204 4] Value : 00000000
+[0D0h 0208 4] Register Mask : 000003FF
+
+[0D4h 0212 1] Watchdog Action : 05
+[0D5h 0213 1] Instruction : 01
+[0D6h 0214 2] Reserved : 0000
+
+[0D8h 0216 12] Register Region : [Generic Address Structure]
+[0D8h 0216 1] Space ID : 01 [SystemIO]
+[0D9h 0217 1] Bit Width : 10
+[0DAh 0218 1] Bit Offset : 00
+[0DBh 0219 1] Encoded Access Width : 02 [Word Access:16]
+[0DCh 0220 8] Address : 0000000000000672
+
+[0E4h 0228 4] Value : 00000000
+[0E8h 0232 4] Register Mask : 000003FF
+
+[0ECh 0236 1] Watchdog Action : 20
+[0EDh 0237 1] Instruction : 00
+[0EEh 0238 2] Reserved : 0000
+
+[0F0h 0240 12] Register Region : [Generic Address Structure]
+[0F0h 0240 1] Space ID : 01 [SystemIO]
+[0F1h 0241 1] Bit Width : 10
+[0F2h 0242 1] Bit Offset : 00
+[0F3h 0243 1] Encoded Access Width : 02 [Word Access:16]
+[0F4h 0244 8] Address : 0000000000000666
+
+[0FCh 0252 4] Value : 00000002
+[100h 0256 4] Register Mask : 00000002
+
+[104h 0260 1] Watchdog Action : 21
+[105h 0261 1] Instruction : 82
+[106h 0262 2] Reserved : 0000
+
+[108h 0264 12] Register Region : [Generic Address Structure]
+[108h 0264 1] Space ID : 01 [SystemIO]
+[109h 0265 1] Bit Width : 10
+[10Ah 0266 1] Bit Offset : 00
+[10Bh 0267 1] Encoded Access Width : 02 [Word Access:16]
+[10Ch 0268 8] Address : 0000000000000666
+
+[114h 0276 4] Value : 00000002
+[118h 0280 4] Register Mask : 00000002
+
+[11Ch 0284 1] Watchdog Action : 21
+[11Dh 0285 1] Instruction : 82
+[11Eh 0286 2] Reserved : 0000
+
+[120h 0288 12] Register Region : [Generic Address Structure]
+[120h 0288 1] Space ID : 01 [SystemIO]
+[121h 0289 1] Bit Width : 10
+[122h 0290 1] Bit Offset : 00
+[123h 0291 1] Encoded Access Width : 02 [Word Access:16]
+[124h 0292 8] Address : 0000000000000666
+
+[12Ch 0300 4] Value : 00000004
+[130h 0304 4] Register Mask : 00000004
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Acked-by: Ani Sinha <anisinha@redhat.com>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 -
tests/data/acpi/x86/q35/WDAT.wdat | Bin 0 -> 308 bytes
2 files changed, 1 deletion(-)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index 14b680debe..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,2 +1 @@
/* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/x86/q35/WDAT.wdat",
diff --git a/tests/data/acpi/x86/q35/WDAT.wdat b/tests/data/acpi/x86/q35/WDAT.wdat
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e1e056b390e51c49f11f7b0d35e4e7c55d8067b1 100644
GIT binary patch
literal 308
zcmaivF$w}f3`JkEx{TV)5#kX9FW|0)oq~c}T8Xtc(2GYhPO+$9AY^#?`OH6WH>b6L
zth#-_J6bm!dNVTt;vLff$K8QJ!5f$W4`2?6f@Jj4QYvm-AjK}Dx5`T;m_2{<;x*QX
lL4w7nzVfzt``kzV@waK@$$at15&T;93Z<9T{~wRc(JwJ97XbhO
literal 0
HcmV?d00001
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 06/21] tests: acpi: x86/q35: update expected WDAT blob
2026-03-03 9:25 ` [PATCH v2 06/21] tests: acpi: x86/q35: update expected WDAT blob Igor Mammedov
@ 2026-05-13 15:48 ` Zhao Liu
0 siblings, 0 replies; 57+ messages in thread
From: Zhao Liu @ 2026-05-13 15:48 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, rad, leif.lindholm, qemu-arm
On Tue, Mar 03, 2026 at 10:25:17AM +0100, Igor Mammedov wrote:
> Date: Tue, 3 Mar 2026 10:25:17 +0100
> From: Igor Mammedov <imammedo@redhat.com>
> Subject: [PATCH v2 06/21] tests: acpi: x86/q35: update expected WDAT blob
>
> replace blank table with a new one:
>
> +[000h 0000 4] Signature : "WDAT" [Watchdog Action Table]
> +[004h 0004 4] Table Length : 00000134
> +[008h 0008 1] Revision : 01
> +[009h 0009 1] Checksum : 31
> +[00Ah 0010 6] Oem ID : "BOCHS "
> +[010h 0016 8] Oem Table ID : "BXPC "
> +[018h 0024 4] Oem Revision : 00000001
> +[01Ch 0028 4] Asl Compiler ID : "BXPC"
> +[020h 0032 4] Asl Compiler Revision : 00000001
> +
> +[024h 0036 4] Header Length : 00000020
> +[028h 0040 2] PCI Segment : 00FF
> +[02Ah 0042 1] PCI Bus : FF
> +[02Bh 0043 1] PCI Device : FF
> +[02Ch 0044 1] PCI Function : FF
> +[02Dh 0045 3] Reserved : 000000
> +[030h 0048 4] Timer Period : 00000258
> +[034h 0052 4] Max Count : 000003FF
> +[038h 0056 4] Min Count : 00000004
> +[03Ch 0060 1] Flags (decoded below) : 81
> + Enabled : 1
> + Stopped When Asleep : 1
> +[03Dh 0061 3] Reserved : 000000
> +[040h 0064 4] Watchdog Entry Count : 0000000A
> +
> +[044h 0068 1] Watchdog Action : 01
> +[045h 0069 1] Instruction : 02
> +[046h 0070 2] Reserved : 0000
> +
> +[048h 0072 12] Register Region : [Generic Address Structure]
> +[048h 0072 1] Space ID : 01 [SystemIO]
> +[049h 0073 1] Bit Width : 10
> +[04Ah 0074 1] Bit Offset : 00
> +[04Bh 0075 1] Encoded Access Width : 02 [Word Access:16]
> +[04Ch 0076 8] Address : 0000000000000660
> +
> +[054h 0084 4] Value : 00000001
> +[058h 0088 4] Register Mask : 000001FF
> +
> +[05Ch 0092 1] Watchdog Action : 08
> +[05Dh 0093 1] Instruction : 00
> +[05Eh 0094 2] Reserved : 0000
> +
> +[060h 0096 12] Register Region : [Generic Address Structure]
> +[060h 0096 1] Space ID : 01 [SystemIO]
> +[061h 0097 1] Bit Width : 10
> +[062h 0098 1] Bit Offset : 00
> +[063h 0099 1] Encoded Access Width : 02 [Word Access:16]
> +[064h 0100 8] Address : 0000000000000668
> +
> +[06Ch 0108 4] Value : 00000000
> +[070h 0112 4] Register Mask : 00000800
> +
> +[074h 0116 1] Watchdog Action : 09
> +[075h 0117 1] Instruction : 82
> +[076h 0118 2] Reserved : 0000
> +
> +[078h 0120 12] Register Region : [Generic Address Structure]
> +[078h 0120 1] Space ID : 01 [SystemIO]
> +[079h 0121 1] Bit Width : 10
> +[07Ah 0122 1] Bit Offset : 00
> +[07Bh 0123 1] Encoded Access Width : 02 [Word Access:16]
> +[07Ch 0124 8] Address : 0000000000000668
> +
> +[084h 0132 4] Value : 00000000
> +[088h 0136 4] Register Mask : 00000800
> +
> +[08Ch 0140 1] Watchdog Action : 0A
> +[08Dh 0141 1] Instruction : 00
> +[08Eh 0142 2] Reserved : 0000
> +
> +[090h 0144 12] Register Region : [Generic Address Structure]
> +[090h 0144 1] Space ID : 01 [SystemIO]
> +[091h 0145 1] Bit Width : 10
> +[092h 0146 1] Bit Offset : 00
> +[093h 0147 1] Encoded Access Width : 02 [Word Access:16]
> +[094h 0148 8] Address : 0000000000000668
> +
> +[09Ch 0156 4] Value : 00000800
> +[0A0h 0160 4] Register Mask : 00000800
> +
> +[0A4h 0164 1] Watchdog Action : 0B
> +[0A5h 0165 1] Instruction : 82
> +[0A6h 0166 2] Reserved : 0000
> +
> +[0A8h 0168 12] Register Region : [Generic Address Structure]
> +[0A8h 0168 1] Space ID : 01 [SystemIO]
> +[0A9h 0169 1] Bit Width : 10
> +[0AAh 0170 1] Bit Offset : 00
> +[0ABh 0171 1] Encoded Access Width : 02 [Word Access:16]
> +[0ACh 0172 8] Address : 0000000000000668
> +
> +[0B4h 0180 4] Value : 00000800
> +[0B8h 0184 4] Register Mask : 00000800
> +
> +[0BCh 0188 1] Watchdog Action : 06
> +[0BDh 0189 1] Instruction : 03
> +[0BEh 0190 2] Reserved : 0000
> +
> +[0C0h 0192 12] Register Region : [Generic Address Structure]
> +[0C0h 0192 1] Space ID : 01 [SystemIO]
> +[0C1h 0193 1] Bit Width : 10
> +[0C2h 0194 1] Bit Offset : 00
> +[0C3h 0195 1] Encoded Access Width : 02 [Word Access:16]
> +[0C4h 0196 8] Address : 0000000000000672
> +
> +[0CCh 0204 4] Value : 00000000
> +[0D0h 0208 4] Register Mask : 000003FF
> +
> +[0D4h 0212 1] Watchdog Action : 05
> +[0D5h 0213 1] Instruction : 01
> +[0D6h 0214 2] Reserved : 0000
> +
> +[0D8h 0216 12] Register Region : [Generic Address Structure]
> +[0D8h 0216 1] Space ID : 01 [SystemIO]
> +[0D9h 0217 1] Bit Width : 10
> +[0DAh 0218 1] Bit Offset : 00
> +[0DBh 0219 1] Encoded Access Width : 02 [Word Access:16]
> +[0DCh 0220 8] Address : 0000000000000672
> +
> +[0E4h 0228 4] Value : 00000000
> +[0E8h 0232 4] Register Mask : 000003FF
> +
> +[0ECh 0236 1] Watchdog Action : 20
> +[0EDh 0237 1] Instruction : 00
> +[0EEh 0238 2] Reserved : 0000
> +
> +[0F0h 0240 12] Register Region : [Generic Address Structure]
> +[0F0h 0240 1] Space ID : 01 [SystemIO]
> +[0F1h 0241 1] Bit Width : 10
> +[0F2h 0242 1] Bit Offset : 00
> +[0F3h 0243 1] Encoded Access Width : 02 [Word Access:16]
> +[0F4h 0244 8] Address : 0000000000000666
> +
> +[0FCh 0252 4] Value : 00000002
> +[100h 0256 4] Register Mask : 00000002
> +
> +[104h 0260 1] Watchdog Action : 21
> +[105h 0261 1] Instruction : 82
> +[106h 0262 2] Reserved : 0000
> +
> +[108h 0264 12] Register Region : [Generic Address Structure]
> +[108h 0264 1] Space ID : 01 [SystemIO]
> +[109h 0265 1] Bit Width : 10
> +[10Ah 0266 1] Bit Offset : 00
> +[10Bh 0267 1] Encoded Access Width : 02 [Word Access:16]
> +[10Ch 0268 8] Address : 0000000000000666
> +
> +[114h 0276 4] Value : 00000002
> +[118h 0280 4] Register Mask : 00000002
> +
> +[11Ch 0284 1] Watchdog Action : 21
> +[11Dh 0285 1] Instruction : 82
> +[11Eh 0286 2] Reserved : 0000
> +
> +[120h 0288 12] Register Region : [Generic Address Structure]
> +[120h 0288 1] Space ID : 01 [SystemIO]
> +[121h 0289 1] Bit Width : 10
> +[122h 0290 1] Bit Offset : 00
> +[123h 0291 1] Encoded Access Width : 02 [Word Access:16]
> +[124h 0292 8] Address : 0000000000000666
> +
> +[12Ch 0300 4] Value : 00000004
> +[130h 0304 4] Register Mask : 00000004
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Acked-by: Ani Sinha <anisinha@redhat.com>
> ---
> tests/qtest/bios-tables-test-allowed-diff.h | 1 -
> tests/data/acpi/x86/q35/WDAT.wdat | Bin 0 -> 308 bytes
> 2 files changed, 1 deletion(-)
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 07/21] arm: sbsa_gwdt: fixup default "clock-frequency"
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (5 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 06/21] tests: acpi: x86/q35: update expected WDAT blob Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-26 14:19 ` Eric Auger
2026-06-03 6:15 ` Michael S. Tsirkin
2026-03-03 9:25 ` [PATCH v2 08/21] arm: add tracing events to sbsa_gwdt Igor Mammedov
` (15 subsequent siblings)
22 siblings, 2 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Comment about keeping legacy freq, is wrong to begin with
(should be 62.5MHz), but that value also doesn't make
sense anymore as the watchdog is used only by un-versioned
SBSA board and the later has hard-coded it to 1GHz.
Other potential user (arm/virt) also has system clock at 1GHz.
Drop misleading comment about legacy and set default to 1GHz
to match both boards.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
hw/watchdog/sbsa_gwdt.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index 7ade5c6f18..b739a3ce3c 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -264,11 +264,10 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
static const Property wdt_sbsa_gwdt_props[] = {
/*
* Timer frequency in Hz. This must match the frequency used by
- * the CPU's generic timer. Default 62.5Hz matches QEMU's legacy
- * CPU timer frequency default.
+ * the CPU's generic timer.
*/
DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
- 62500000),
+ 1000000000),
};
static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 07/21] arm: sbsa_gwdt: fixup default "clock-frequency"
2026-03-03 9:25 ` [PATCH v2 07/21] arm: sbsa_gwdt: fixup default "clock-frequency" Igor Mammedov
@ 2026-05-26 14:19 ` Eric Auger
2026-06-03 6:15 ` Michael S. Tsirkin
1 sibling, 0 replies; 57+ messages in thread
From: Eric Auger @ 2026-05-26 14:19 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> Comment about keeping legacy freq, is wrong to begin with
> (should be 62.5MHz), but that value also doesn't make
> sense anymore as the watchdog is used only by un-versioned
> SBSA board and the later has hard-coded it to 1GHz.
>
> Other potential user (arm/virt) also has system clock at 1GHz.
>
> Drop misleading comment about legacy and set default to 1GHz
> to match both boards.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> hw/watchdog/sbsa_gwdt.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> index 7ade5c6f18..b739a3ce3c 100644
> --- a/hw/watchdog/sbsa_gwdt.c
> +++ b/hw/watchdog/sbsa_gwdt.c
> @@ -264,11 +264,10 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
> static const Property wdt_sbsa_gwdt_props[] = {
> /*
> * Timer frequency in Hz. This must match the frequency used by
> - * the CPU's generic timer. Default 62.5Hz matches QEMU's legacy
> - * CPU timer frequency default.
> + * the CPU's generic timer.
> */
> DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
> - 62500000),
> + 1000000000),
> };
>
> static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 07/21] arm: sbsa_gwdt: fixup default "clock-frequency"
2026-03-03 9:25 ` [PATCH v2 07/21] arm: sbsa_gwdt: fixup default "clock-frequency" Igor Mammedov
2026-05-26 14:19 ` Eric Auger
@ 2026-06-03 6:15 ` Michael S. Tsirkin
1 sibling, 0 replies; 57+ messages in thread
From: Michael S. Tsirkin @ 2026-06-03 6:15 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, anisinha, pbonzini, peter.maydell, shannon.zhaosl,
philmd, zhao1.liu, rad, leif.lindholm, qemu-arm
On Tue, Mar 03, 2026 at 10:25:18AM +0100, Igor Mammedov wrote:
> Comment about keeping legacy freq, is wrong to begin with
> (should be 62.5MHz), but that value also doesn't make
> sense anymore as the watchdog is used only by un-versioned
> SBSA board and the later has hard-coded it to 1GHz.
>
> Other potential user (arm/virt) also has system clock at 1GHz.
>
> Drop misleading comment about legacy and set default to 1GHz
> to match both boards.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
if I take this in isolation then make check seems to fail
on qemu:qtest-arm/aspeed_smc-test.
follow up patches fix it, but I think it has to be reordered
to avoid breaking bisect.
> ---
> hw/watchdog/sbsa_gwdt.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> index 7ade5c6f18..b739a3ce3c 100644
> --- a/hw/watchdog/sbsa_gwdt.c
> +++ b/hw/watchdog/sbsa_gwdt.c
> @@ -264,11 +264,10 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
> static const Property wdt_sbsa_gwdt_props[] = {
> /*
> * Timer frequency in Hz. This must match the frequency used by
> - * the CPU's generic timer. Default 62.5Hz matches QEMU's legacy
> - * CPU timer frequency default.
> + * the CPU's generic timer.
> */
> DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
> - 62500000),
> + 1000000000),
> };
>
> static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
> --
> 2.47.3
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 08/21] arm: add tracing events to sbsa_gwdt
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (6 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 07/21] arm: sbsa_gwdt: fixup default "clock-frequency" Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-26 14:02 ` Eric Auger
2026-03-03 9:25 ` [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog Igor Mammedov
` (14 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Ani Sinha <anisinha@redhat.com>
---
hw/watchdog/sbsa_gwdt.c | 8 ++++++++
hw/watchdog/trace-events | 9 +++++++++
2 files changed, 17 insertions(+)
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index b739a3ce3c..acb970e8b3 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -24,6 +24,7 @@
#include "migration/vmstate.h"
#include "qemu/log.h"
#include "qemu/module.h"
+#include "trace.h"
static const VMStateDescription vmstate_sbsa_gwdt = {
.name = "sbsa-gwdt",
@@ -62,6 +63,7 @@ static uint64_t sbsa_gwdt_rread(void *opaque, hwaddr addr, unsigned int size)
qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame read :"
" 0x%x\n", (int)addr);
}
+ trace_sbsa_gwdt_refresh_read(addr, ret);
return ret;
}
@@ -93,6 +95,7 @@ static uint64_t sbsa_gwdt_read(void *opaque, hwaddr addr, unsigned int size)
qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame read :"
" 0x%x\n", (int)addr);
}
+ trace_sbsa_gwdt_control_read(addr, ret);
return ret;
}
@@ -127,6 +130,7 @@ static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data,
unsigned size) {
SBSA_GWDTState *s = SBSA_GWDT(opaque);
+ trace_sbsa_gwdt_refresh_write(offset, data);
if (offset == SBSA_GWDT_WRR) {
s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
@@ -141,6 +145,7 @@ static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data,
unsigned size) {
SBSA_GWDTState *s = SBSA_GWDT(opaque);
+ trace_sbsa_gwdt_control_write(offset, data);
switch (offset) {
case SBSA_GWDT_WCS:
s->wcs = data & SBSA_GWDT_WCS_EN;
@@ -180,6 +185,7 @@ static void wdt_sbsa_gwdt_reset(DeviceState *dev)
{
SBSA_GWDTState *s = SBSA_GWDT(dev);
+ trace_sbsa_gwdt_reset();
timer_del(s->timer);
s->wcs = 0;
@@ -196,10 +202,12 @@ static void sbsa_gwdt_timer_sysinterrupt(void *opaque)
if (!(s->wcs & SBSA_GWDT_WCS_WS0)) {
s->wcs |= SBSA_GWDT_WCS_WS0;
+ trace_sbsa_gwdt_ws0_asserted();
sbsa_gwdt_update_timer(s, TIMEOUT_REFRESH);
qemu_set_irq(s->irq, 1);
} else {
s->wcs |= SBSA_GWDT_WCS_WS1;
+ trace_sbsa_gwdt_ws1_asserted();
qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
/*
* Reset the watchdog only if the guest gets notified about
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
index ad3be1e9bd..a5c10882f4 100644
--- a/hw/watchdog/trace-events
+++ b/hw/watchdog/trace-events
@@ -33,3 +33,12 @@ spapr_watchdog_expired(uint64_t num, unsigned action) "num=%" PRIu64 " action=%u
# watchdog.c
watchdog_perform_action(unsigned int action) "action=%u"
watchdog_set_action(unsigned int action) "action=%u"
+
+#sbsa_gwdt.c
+sbsa_gwdt_refresh_read(uint64_t addr, uint32_t value) "[0x%" PRIx64 "] -> 0x%" PRIx32
+sbsa_gwdt_refresh_write(uint64_t addr, uint64_t value) "[0x%" PRIx64 "] <- 0x%" PRIx64
+sbsa_gwdt_control_read(uint64_t addr, uint32_t value) "[0x%" PRIx64 "] -> 0x%" PRIx32
+sbsa_gwdt_control_write(uint64_t addr, uint64_t value) "[0x%" PRIx64 "] <- 0x%" PRIx64
+sbsa_gwdt_ws0_asserted(void) "WS0 signal is asserted"
+sbsa_gwdt_ws1_asserted(void) "WS1 signal is asserted"
+sbsa_gwdt_reset(void) "reset watchdog to default state"
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 08/21] arm: add tracing events to sbsa_gwdt
2026-03-03 9:25 ` [PATCH v2 08/21] arm: add tracing events to sbsa_gwdt Igor Mammedov
@ 2026-05-26 14:02 ` Eric Auger
0 siblings, 0 replies; 57+ messages in thread
From: Eric Auger @ 2026-05-26 14:02 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Reviewed-by: Ani Sinha <anisinha@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> hw/watchdog/sbsa_gwdt.c | 8 ++++++++
> hw/watchdog/trace-events | 9 +++++++++
> 2 files changed, 17 insertions(+)
>
> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> index b739a3ce3c..acb970e8b3 100644
> --- a/hw/watchdog/sbsa_gwdt.c
> +++ b/hw/watchdog/sbsa_gwdt.c
> @@ -24,6 +24,7 @@
> #include "migration/vmstate.h"
> #include "qemu/log.h"
> #include "qemu/module.h"
> +#include "trace.h"
>
> static const VMStateDescription vmstate_sbsa_gwdt = {
> .name = "sbsa-gwdt",
> @@ -62,6 +63,7 @@ static uint64_t sbsa_gwdt_rread(void *opaque, hwaddr addr, unsigned int size)
> qemu_log_mask(LOG_GUEST_ERROR, "bad address in refresh frame read :"
> " 0x%x\n", (int)addr);
> }
> + trace_sbsa_gwdt_refresh_read(addr, ret);
> return ret;
> }
>
> @@ -93,6 +95,7 @@ static uint64_t sbsa_gwdt_read(void *opaque, hwaddr addr, unsigned int size)
> qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame read :"
> " 0x%x\n", (int)addr);
> }
> + trace_sbsa_gwdt_control_read(addr, ret);
> return ret;
> }
>
> @@ -127,6 +130,7 @@ static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data,
> unsigned size) {
> SBSA_GWDTState *s = SBSA_GWDT(opaque);
>
> + trace_sbsa_gwdt_refresh_write(offset, data);
> if (offset == SBSA_GWDT_WRR) {
> s->wcs &= ~(SBSA_GWDT_WCS_WS0 | SBSA_GWDT_WCS_WS1);
>
> @@ -141,6 +145,7 @@ static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data,
> unsigned size) {
> SBSA_GWDTState *s = SBSA_GWDT(opaque);
>
> + trace_sbsa_gwdt_control_write(offset, data);
> switch (offset) {
> case SBSA_GWDT_WCS:
> s->wcs = data & SBSA_GWDT_WCS_EN;
> @@ -180,6 +185,7 @@ static void wdt_sbsa_gwdt_reset(DeviceState *dev)
> {
> SBSA_GWDTState *s = SBSA_GWDT(dev);
>
> + trace_sbsa_gwdt_reset();
> timer_del(s->timer);
>
> s->wcs = 0;
> @@ -196,10 +202,12 @@ static void sbsa_gwdt_timer_sysinterrupt(void *opaque)
>
> if (!(s->wcs & SBSA_GWDT_WCS_WS0)) {
> s->wcs |= SBSA_GWDT_WCS_WS0;
> + trace_sbsa_gwdt_ws0_asserted();
> sbsa_gwdt_update_timer(s, TIMEOUT_REFRESH);
> qemu_set_irq(s->irq, 1);
> } else {
> s->wcs |= SBSA_GWDT_WCS_WS1;
> + trace_sbsa_gwdt_ws1_asserted();
> qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
> /*
> * Reset the watchdog only if the guest gets notified about
> diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
> index ad3be1e9bd..a5c10882f4 100644
> --- a/hw/watchdog/trace-events
> +++ b/hw/watchdog/trace-events
> @@ -33,3 +33,12 @@ spapr_watchdog_expired(uint64_t num, unsigned action) "num=%" PRIu64 " action=%u
> # watchdog.c
> watchdog_perform_action(unsigned int action) "action=%u"
> watchdog_set_action(unsigned int action) "action=%u"
> +
> +#sbsa_gwdt.c
> +sbsa_gwdt_refresh_read(uint64_t addr, uint32_t value) "[0x%" PRIx64 "] -> 0x%" PRIx32
> +sbsa_gwdt_refresh_write(uint64_t addr, uint64_t value) "[0x%" PRIx64 "] <- 0x%" PRIx64
> +sbsa_gwdt_control_read(uint64_t addr, uint32_t value) "[0x%" PRIx64 "] -> 0x%" PRIx32
> +sbsa_gwdt_control_write(uint64_t addr, uint64_t value) "[0x%" PRIx64 "] <- 0x%" PRIx64
> +sbsa_gwdt_ws0_asserted(void) "WS0 signal is asserted"
> +sbsa_gwdt_ws1_asserted(void) "WS1 signal is asserted"
> +sbsa_gwdt_reset(void) "reset watchdog to default state"
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (7 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 08/21] arm: add tracing events to sbsa_gwdt Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-26 13:58 ` Eric Auger
2026-06-04 16:48 ` Eric Auger
2026-03-03 9:25 ` [PATCH v2 10/21] arm: sbsa_gwdt: add 'wdat' option Igor Mammedov
` (13 subsequent siblings)
22 siblings, 2 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Allow to use SBSA generic watchdog with virt machine type.
(includes conditional generation of corresponding FDT and
ACPI GTDT descriptors)
Use '-device sbsa_gwdt' to command line to enable it.
Tested with Fedora 43:
FDT: -M virt,acpi=off -device sbsa_gwdt
ACPI: -M virt -device sbsa_gwdt
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
hw/arm/Kconfig | 1 +
hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
hw/arm/virt.c | 2 ++
hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
hw/watchdog/sbsa_gwdt.c | 1 +
5 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index c66c452737..1222efadd1 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -36,6 +36,7 @@ config ARM_VIRT
select VIRTIO_MEM_SUPPORTED
select ACPI_CXL
select ACPI_HMAT
+ select WDT_SBSA
config CUBIEBOARD
bool
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 719d2f994e..9c14b1d4d5 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -64,6 +64,7 @@
#include "hw/virtio/virtio-acpi.h"
#include "target/arm/cpu.h"
#include "target/arm/multiprocessing.h"
+#include "hw/watchdog/sbsa_gwdt.h"
#define ARM_SPI_BASE 32
@@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
const uint32_t irqflags = 0; /* Interrupt is Level triggered */
AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
.oem_table_id = vms->oem_table_id };
+ uint32_t gtdt_start = table_data->len;
+ Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
acpi_table_begin(&table, table_data);
@@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
build_append_int_noprefix(table_data, irqflags, 4);
/* CntReadBase Physical address */
build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
+
/* Platform Timer Count */
- build_append_int_noprefix(table_data, 0, 4);
+ build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
/* Platform Timer Offset */
- build_append_int_noprefix(table_data, 0, 4);
+ build_append_int_noprefix(table_data,
+ wdt ? (table_data->len - gtdt_start) +
+ 4 + 4 + 4 /* len of this & following 2 fields to skip */
+ : 0, 4);
+
if (vms->ns_el2_virt_timer_irq) {
/* Virtual EL2 Timer GSIV */
build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
@@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
build_append_int_noprefix(table_data, 0, 4);
build_append_int_noprefix(table_data, 0, 4);
}
+
+ /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
+ if (wdt) {
+ PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
+ SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
+ hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
+ hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
+ hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
+ int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
+ platform_bus_get_irqn(pbus, sd, 0);
+
+ build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
+ build_append_int_noprefix(table_data, 28 /* Length */, 2);
+ build_append_int_noprefix(table_data, 0, 1); /* Reserved */
+ /* RefreshFrame Physical Address */
+ build_append_int_noprefix(table_data, rbase, 8);
+ /* WatchdogControlFrame Physical Address */
+ build_append_int_noprefix(table_data, cbase, 8);
+ build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
+ build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
+ }
acpi_table_end(linker, &table);
}
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index cab2e21e8a..a87991b591 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -95,6 +95,7 @@
#include "hw/cxl/cxl.h"
#include "hw/cxl/cxl_host.h"
#include "qemu/guest-random.h"
+#include "hw/watchdog/sbsa_gwdt.h"
static GlobalProperty arm_virt_compat_defaults[] = {
{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
@@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
#ifdef CONFIG_TPM
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
#endif
diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
index 89d0c46445..76aa1bc579 100644
--- a/hw/core/sysbus-fdt.c
+++ b/hw/core/sysbus-fdt.c
@@ -36,6 +36,7 @@
#include "hw/display/ramfb.h"
#include "hw/uefi/var-service-api.h"
#include "hw/arm/fdt.h"
+#include "hw/watchdog/sbsa_gwdt.h"
/*
* internal struct that contains the information to create dynamic
@@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
return 0;
}
+static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
+{
+ PlatformBusFDTData *data = opaque;
+ PlatformBusDevice *pbus = data->pbus;
+ const char *parent_node = data->pbus_node_name;
+ void *fdt = data->fdt;
+ uint64_t cbase, rbase;
+ char *nodename;
+ int irq;
+
+ cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
+ rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
+ irq = platform_bus_get_irqn(pbus, sbdev, 0);
+
+ nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
+ qemu_fdt_add_subnode(fdt, nodename);
+
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
+ cbase, SBSA_GWDT_CMMIO_SIZE,
+ rbase, SBSA_GWDT_RMMIO_SIZE);
+ qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
+ GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+ qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
+
+ g_free(nodename);
+ return 0;
+}
+
static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
{
return 0;
@@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
+ TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
TYPE_BINDING("", NULL), /* last element */
};
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index acb970e8b3..c4dd8005b7 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
dc->realize = wdt_sbsa_gwdt_realize;
device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
dc->hotpluggable = false;
+ dc->user_creatable = true;
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->vmsd = &vmstate_sbsa_gwdt;
dc->desc = "SBSA-compliant generic watchdog device";
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-03-03 9:25 ` [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog Igor Mammedov
@ 2026-05-26 13:58 ` Eric Auger
2026-05-27 12:49 ` Igor Mammedov
2026-06-04 16:48 ` Eric Auger
1 sibling, 1 reply; 57+ messages in thread
From: Eric Auger @ 2026-05-26 13:58 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Hi Igor,
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> Allow to use SBSA generic watchdog with virt machine type.
> (includes conditional generation of corresponding FDT and
> ACPI GTDT descriptors)
>
> Use '-device sbsa_gwdt' to command line to enable it.
I thank that in general Peter is not a big fan of dynamic instantiation
of sysbus devices. Don't you have means to instantiate it statically in
arm virt memory map?
Eric
>
> Tested with Fedora 43:
> FDT: -M virt,acpi=off -device sbsa_gwdt
> ACPI: -M virt -device sbsa_gwdt
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> hw/arm/Kconfig | 1 +
> hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
> hw/arm/virt.c | 2 ++
> hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
> hw/watchdog/sbsa_gwdt.c | 1 +
> 5 files changed, 67 insertions(+), 2 deletions(-)
>
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index c66c452737..1222efadd1 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -36,6 +36,7 @@ config ARM_VIRT
> select VIRTIO_MEM_SUPPORTED
> select ACPI_CXL
> select ACPI_HMAT
> + select WDT_SBSA
>
> config CUBIEBOARD
> bool
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 719d2f994e..9c14b1d4d5 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -64,6 +64,7 @@
> #include "hw/virtio/virtio-acpi.h"
> #include "target/arm/cpu.h"
> #include "target/arm/multiprocessing.h"
> +#include "hw/watchdog/sbsa_gwdt.h"
>
> #define ARM_SPI_BASE 32
>
> @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> const uint32_t irqflags = 0; /* Interrupt is Level triggered */
> AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
> .oem_table_id = vms->oem_table_id };
> + uint32_t gtdt_start = table_data->len;
> + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
>
> acpi_table_begin(&table, table_data);
>
> @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> build_append_int_noprefix(table_data, irqflags, 4);
> /* CntReadBase Physical address */
> build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
> +
> /* Platform Timer Count */
> - build_append_int_noprefix(table_data, 0, 4);
> + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
> /* Platform Timer Offset */
> - build_append_int_noprefix(table_data, 0, 4);
> + build_append_int_noprefix(table_data,
> + wdt ? (table_data->len - gtdt_start) +
> + 4 + 4 + 4 /* len of this & following 2 fields to skip */
> + : 0, 4);
> +
> if (vms->ns_el2_virt_timer_irq) {
> /* Virtual EL2 Timer GSIV */
> build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
> @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> build_append_int_noprefix(table_data, 0, 4);
> build_append_int_noprefix(table_data, 0, 4);
> }
> +
> + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
> + if (wdt) {
> + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
> + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
> + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
> + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
> + platform_bus_get_irqn(pbus, sd, 0);
> +
> + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
> + build_append_int_noprefix(table_data, 28 /* Length */, 2);
> + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
> + /* RefreshFrame Physical Address */
> + build_append_int_noprefix(table_data, rbase, 8);
> + /* WatchdogControlFrame Physical Address */
> + build_append_int_noprefix(table_data, cbase, 8);
> + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
> + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
> + }
> acpi_table_end(linker, &table);
> }
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index cab2e21e8a..a87991b591 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -95,6 +95,7 @@
> #include "hw/cxl/cxl.h"
> #include "hw/cxl/cxl_host.h"
> #include "qemu/guest-random.h"
> +#include "hw/watchdog/sbsa_gwdt.h"
>
> static GlobalProperty arm_virt_compat_defaults[] = {
> { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
> @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
> + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
> #ifdef CONFIG_TPM
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> #endif
> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> index 89d0c46445..76aa1bc579 100644
> --- a/hw/core/sysbus-fdt.c
> +++ b/hw/core/sysbus-fdt.c
> @@ -36,6 +36,7 @@
> #include "hw/display/ramfb.h"
> #include "hw/uefi/var-service-api.h"
> #include "hw/arm/fdt.h"
> +#include "hw/watchdog/sbsa_gwdt.h"
>
> /*
> * internal struct that contains the information to create dynamic
> @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
> return 0;
> }
>
> +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
> +{
> + PlatformBusFDTData *data = opaque;
> + PlatformBusDevice *pbus = data->pbus;
> + const char *parent_node = data->pbus_node_name;
> + void *fdt = data->fdt;
> + uint64_t cbase, rbase;
> + char *nodename;
> + int irq;
> +
> + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
> + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
> + irq = platform_bus_get_irqn(pbus, sbdev, 0);
> +
> + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
> + qemu_fdt_add_subnode(fdt, nodename);
> +
> + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
> + qemu_fdt_setprop_cells(fdt, nodename, "reg",
> + cbase, SBSA_GWDT_CMMIO_SIZE,
> + rbase, SBSA_GWDT_RMMIO_SIZE);
> + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
> + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
> +
> + g_free(nodename);
> + return 0;
> +}
> +
> static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
> {
> return 0;
> @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
> TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
> TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
> TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
> + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
> TYPE_BINDING("", NULL), /* last element */
> };
>
> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> index acb970e8b3..c4dd8005b7 100644
> --- a/hw/watchdog/sbsa_gwdt.c
> +++ b/hw/watchdog/sbsa_gwdt.c
> @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
> dc->realize = wdt_sbsa_gwdt_realize;
> device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
> dc->hotpluggable = false;
> + dc->user_creatable = true;
> set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
> dc->vmsd = &vmstate_sbsa_gwdt;
> dc->desc = "SBSA-compliant generic watchdog device";
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-05-26 13:58 ` Eric Auger
@ 2026-05-27 12:49 ` Igor Mammedov
2026-05-28 9:04 ` Eric Auger
0 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-05-27 12:49 UTC (permalink / raw)
To: Eric Auger
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm
On Tue, 26 May 2026 15:58:08 +0200
Eric Auger <eauger@redhat.com> wrote:
> Hi Igor,
>
> On 3/3/26 10:25 AM, Igor Mammedov wrote:
> > Allow to use SBSA generic watchdog with virt machine type.
> > (includes conditional generation of corresponding FDT and
> > ACPI GTDT descriptors)
> >
> > Use '-device sbsa_gwdt' to command line to enable it.
> I thank that in general Peter is not a big fan of dynamic instantiation
> of sysbus devices. Don't you have means to instantiate it statically in
> arm virt memory map?
/me neither
in previous version there was a machine option to enable the feature
to that was rejected in favor of device.
in this case for platform -device of sysbus based device, I don't think
we can do better that dynamic sysbus.
>
> Eric
> >
> > Tested with Fedora 43:
> > FDT: -M virt,acpi=off -device sbsa_gwdt
> > ACPI: -M virt -device sbsa_gwdt
> >
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > hw/arm/Kconfig | 1 +
> > hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
> > hw/arm/virt.c | 2 ++
> > hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
> > hw/watchdog/sbsa_gwdt.c | 1 +
> > 5 files changed, 67 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index c66c452737..1222efadd1 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -36,6 +36,7 @@ config ARM_VIRT
> > select VIRTIO_MEM_SUPPORTED
> > select ACPI_CXL
> > select ACPI_HMAT
> > + select WDT_SBSA
> >
> > config CUBIEBOARD
> > bool
> > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> > index 719d2f994e..9c14b1d4d5 100644
> > --- a/hw/arm/virt-acpi-build.c
> > +++ b/hw/arm/virt-acpi-build.c
> > @@ -64,6 +64,7 @@
> > #include "hw/virtio/virtio-acpi.h"
> > #include "target/arm/cpu.h"
> > #include "target/arm/multiprocessing.h"
> > +#include "hw/watchdog/sbsa_gwdt.h"
> >
> > #define ARM_SPI_BASE 32
> >
> > @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> > const uint32_t irqflags = 0; /* Interrupt is Level triggered */
> > AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
> > .oem_table_id = vms->oem_table_id };
> > + uint32_t gtdt_start = table_data->len;
> > + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
> >
> > acpi_table_begin(&table, table_data);
> >
> > @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> > build_append_int_noprefix(table_data, irqflags, 4);
> > /* CntReadBase Physical address */
> > build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
> > +
> > /* Platform Timer Count */
> > - build_append_int_noprefix(table_data, 0, 4);
> > + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
> > /* Platform Timer Offset */
> > - build_append_int_noprefix(table_data, 0, 4);
> > + build_append_int_noprefix(table_data,
> > + wdt ? (table_data->len - gtdt_start) +
> > + 4 + 4 + 4 /* len of this & following 2 fields to skip */
> > + : 0, 4);
> > +
> > if (vms->ns_el2_virt_timer_irq) {
> > /* Virtual EL2 Timer GSIV */
> > build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
> > @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> > build_append_int_noprefix(table_data, 0, 4);
> > build_append_int_noprefix(table_data, 0, 4);
> > }
> > +
> > + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
> > + if (wdt) {
> > + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> > + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
> > + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> > + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
> > + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
> > + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
> > + platform_bus_get_irqn(pbus, sd, 0);
> > +
> > + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
> > + build_append_int_noprefix(table_data, 28 /* Length */, 2);
> > + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
> > + /* RefreshFrame Physical Address */
> > + build_append_int_noprefix(table_data, rbase, 8);
> > + /* WatchdogControlFrame Physical Address */
> > + build_append_int_noprefix(table_data, cbase, 8);
> > + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
> > + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
> > + }
> > acpi_table_end(linker, &table);
> > }
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index cab2e21e8a..a87991b591 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -95,6 +95,7 @@
> > #include "hw/cxl/cxl.h"
> > #include "hw/cxl/cxl_host.h"
> > #include "qemu/guest-random.h"
> > +#include "hw/watchdog/sbsa_gwdt.h"
> >
> > static GlobalProperty arm_virt_compat_defaults[] = {
> > { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
> > @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
> > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
> > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
> > + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
> > #ifdef CONFIG_TPM
> > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> > #endif
> > diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> > index 89d0c46445..76aa1bc579 100644
> > --- a/hw/core/sysbus-fdt.c
> > +++ b/hw/core/sysbus-fdt.c
> > @@ -36,6 +36,7 @@
> > #include "hw/display/ramfb.h"
> > #include "hw/uefi/var-service-api.h"
> > #include "hw/arm/fdt.h"
> > +#include "hw/watchdog/sbsa_gwdt.h"
> >
> > /*
> > * internal struct that contains the information to create dynamic
> > @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
> > return 0;
> > }
> >
> > +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
> > +{
> > + PlatformBusFDTData *data = opaque;
> > + PlatformBusDevice *pbus = data->pbus;
> > + const char *parent_node = data->pbus_node_name;
> > + void *fdt = data->fdt;
> > + uint64_t cbase, rbase;
> > + char *nodename;
> > + int irq;
> > +
> > + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
> > + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
> > + irq = platform_bus_get_irqn(pbus, sbdev, 0);
> > +
> > + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
> > + qemu_fdt_add_subnode(fdt, nodename);
> > +
> > + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
> > + qemu_fdt_setprop_cells(fdt, nodename, "reg",
> > + cbase, SBSA_GWDT_CMMIO_SIZE,
> > + rbase, SBSA_GWDT_RMMIO_SIZE);
> > + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
> > + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
> > + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> > + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
> > +
> > + g_free(nodename);
> > + return 0;
> > +}
> > +
> > static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
> > {
> > return 0;
> > @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
> > TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
> > TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
> > TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
> > + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
> > TYPE_BINDING("", NULL), /* last element */
> > };
> >
> > diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> > index acb970e8b3..c4dd8005b7 100644
> > --- a/hw/watchdog/sbsa_gwdt.c
> > +++ b/hw/watchdog/sbsa_gwdt.c
> > @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
> > dc->realize = wdt_sbsa_gwdt_realize;
> > device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
> > dc->hotpluggable = false;
> > + dc->user_creatable = true;
> > set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
> > dc->vmsd = &vmstate_sbsa_gwdt;
> > dc->desc = "SBSA-compliant generic watchdog device";
>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-05-27 12:49 ` Igor Mammedov
@ 2026-05-28 9:04 ` Eric Auger
2026-05-28 9:59 ` Eric Auger
0 siblings, 1 reply; 57+ messages in thread
From: Eric Auger @ 2026-05-28 9:04 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm
Hi Igor,
On 5/27/26 2:49 PM, Igor Mammedov wrote:
> On Tue, 26 May 2026 15:58:08 +0200
> Eric Auger <eauger@redhat.com> wrote:
>
>> Hi Igor,
>>
>> On 3/3/26 10:25 AM, Igor Mammedov wrote:
>>> Allow to use SBSA generic watchdog with virt machine type.
>>> (includes conditional generation of corresponding FDT and
>>> ACPI GTDT descriptors)
>>>
>>> Use '-device sbsa_gwdt' to command line to enable it.
>> I thank that in general Peter is not a big fan of dynamic instantiation
>> of sysbus devices. Don't you have means to instantiate it statically in
>> arm virt memory map?
>
> /me neither
>
> in previous version there was a machine option to enable the feature
> to that was rejected in favor of device.
>
> in this case for platform -device of sysbus based device, I don't think
> we can do better that dynamic sysbus.
sorry I may have missed some previous discussion details. As far as I
can read, I understand you could instantiate the wdt in a free MMIO
slot, unconfitionnaly just as it is done in hw/arm/sbsa-ref.c. Maybe add
a compat to avoid having it by default on older machine types. Then
about the type of the integration gtdt or wat, can't you have a device
compat?
Thanks
Eric
>
>
>>
>> Eric
>>>
>>> Tested with Fedora 43:
>>> FDT: -M virt,acpi=off -device sbsa_gwdt
>>> ACPI: -M virt -device sbsa_gwdt
>>>
>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>>> ---
>>> hw/arm/Kconfig | 1 +
>>> hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
>>> hw/arm/virt.c | 2 ++
>>> hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
>>> hw/watchdog/sbsa_gwdt.c | 1 +
>>> 5 files changed, 67 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>>> index c66c452737..1222efadd1 100644
>>> --- a/hw/arm/Kconfig
>>> +++ b/hw/arm/Kconfig
>>> @@ -36,6 +36,7 @@ config ARM_VIRT
>>> select VIRTIO_MEM_SUPPORTED
>>> select ACPI_CXL
>>> select ACPI_HMAT
>>> + select WDT_SBSA
>>>
>>> config CUBIEBOARD
>>> bool
>>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>>> index 719d2f994e..9c14b1d4d5 100644
>>> --- a/hw/arm/virt-acpi-build.c
>>> +++ b/hw/arm/virt-acpi-build.c
>>> @@ -64,6 +64,7 @@
>>> #include "hw/virtio/virtio-acpi.h"
>>> #include "target/arm/cpu.h"
>>> #include "target/arm/multiprocessing.h"
>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>
>>> #define ARM_SPI_BASE 32
>>>
>>> @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>> const uint32_t irqflags = 0; /* Interrupt is Level triggered */
>>> AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
>>> .oem_table_id = vms->oem_table_id };
>>> + uint32_t gtdt_start = table_data->len;
>>> + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
>>>
>>> acpi_table_begin(&table, table_data);
>>>
>>> @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>> build_append_int_noprefix(table_data, irqflags, 4);
>>> /* CntReadBase Physical address */
>>> build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
>>> +
>>> /* Platform Timer Count */
>>> - build_append_int_noprefix(table_data, 0, 4);
>>> + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
>>> /* Platform Timer Offset */
>>> - build_append_int_noprefix(table_data, 0, 4);
>>> + build_append_int_noprefix(table_data,
>>> + wdt ? (table_data->len - gtdt_start) +
>>> + 4 + 4 + 4 /* len of this & following 2 fields to skip */
>>> + : 0, 4);
>>> +
>>> if (vms->ns_el2_virt_timer_irq) {
>>> /* Virtual EL2 Timer GSIV */
>>> build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
>>> @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>> build_append_int_noprefix(table_data, 0, 4);
>>> build_append_int_noprefix(table_data, 0, 4);
>>> }
>>> +
>>> + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
>>> + if (wdt) {
>>> + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
>>> + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
>>> + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
>>> + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
>>> + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
>>> + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
>>> + platform_bus_get_irqn(pbus, sd, 0);
>>> +
>>> + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
>>> + build_append_int_noprefix(table_data, 28 /* Length */, 2);
>>> + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
>>> + /* RefreshFrame Physical Address */
>>> + build_append_int_noprefix(table_data, rbase, 8);
>>> + /* WatchdogControlFrame Physical Address */
>>> + build_append_int_noprefix(table_data, cbase, 8);
>>> + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
>>> + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
>>> + }
>>> acpi_table_end(linker, &table);
>>> }
>>>
>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>>> index cab2e21e8a..a87991b591 100644
>>> --- a/hw/arm/virt.c
>>> +++ b/hw/arm/virt.c
>>> @@ -95,6 +95,7 @@
>>> #include "hw/cxl/cxl.h"
>>> #include "hw/cxl/cxl_host.h"
>>> #include "qemu/guest-random.h"
>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>
>>> static GlobalProperty arm_virt_compat_defaults[] = {
>>> { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
>>> @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
>>> + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
>>> #ifdef CONFIG_TPM
>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
>>> #endif
>>> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
>>> index 89d0c46445..76aa1bc579 100644
>>> --- a/hw/core/sysbus-fdt.c
>>> +++ b/hw/core/sysbus-fdt.c
>>> @@ -36,6 +36,7 @@
>>> #include "hw/display/ramfb.h"
>>> #include "hw/uefi/var-service-api.h"
>>> #include "hw/arm/fdt.h"
>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>
>>> /*
>>> * internal struct that contains the information to create dynamic
>>> @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
>>> return 0;
>>> }
>>>
>>> +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
>>> +{
>>> + PlatformBusFDTData *data = opaque;
>>> + PlatformBusDevice *pbus = data->pbus;
>>> + const char *parent_node = data->pbus_node_name;
>>> + void *fdt = data->fdt;
>>> + uint64_t cbase, rbase;
>>> + char *nodename;
>>> + int irq;
>>> +
>>> + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
>>> + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
>>> + irq = platform_bus_get_irqn(pbus, sbdev, 0);
>>> +
>>> + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
>>> + qemu_fdt_add_subnode(fdt, nodename);
>>> +
>>> + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
>>> + qemu_fdt_setprop_cells(fdt, nodename, "reg",
>>> + cbase, SBSA_GWDT_CMMIO_SIZE,
>>> + rbase, SBSA_GWDT_RMMIO_SIZE);
>>> + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
>>> + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
>>> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>>> + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
>>> +
>>> + g_free(nodename);
>>> + return 0;
>>> +}
>>> +
>>> static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
>>> {
>>> return 0;
>>> @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
>>> TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
>>> TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
>>> TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
>>> + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
>>> TYPE_BINDING("", NULL), /* last element */
>>> };
>>>
>>> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
>>> index acb970e8b3..c4dd8005b7 100644
>>> --- a/hw/watchdog/sbsa_gwdt.c
>>> +++ b/hw/watchdog/sbsa_gwdt.c
>>> @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
>>> dc->realize = wdt_sbsa_gwdt_realize;
>>> device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
>>> dc->hotpluggable = false;
>>> + dc->user_creatable = true;
>>> set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
>>> dc->vmsd = &vmstate_sbsa_gwdt;
>>> dc->desc = "SBSA-compliant generic watchdog device";
>>
>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-05-28 9:04 ` Eric Auger
@ 2026-05-28 9:59 ` Eric Auger
2026-05-28 14:37 ` Igor Mammedov
0 siblings, 1 reply; 57+ messages in thread
From: Eric Auger @ 2026-05-28 9:59 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm
Hi,
On 5/28/26 11:04 AM, Eric Auger wrote:
> Hi Igor,
>
> On 5/27/26 2:49 PM, Igor Mammedov wrote:
>> On Tue, 26 May 2026 15:58:08 +0200
>> Eric Auger <eauger@redhat.com> wrote:
>>
>>> Hi Igor,
>>>
>>> On 3/3/26 10:25 AM, Igor Mammedov wrote:
>>>> Allow to use SBSA generic watchdog with virt machine type.
>>>> (includes conditional generation of corresponding FDT and
>>>> ACPI GTDT descriptors)
>>>>
>>>> Use '-device sbsa_gwdt' to command line to enable it.
>>> I thank that in general Peter is not a big fan of dynamic instantiation
>>> of sysbus devices. Don't you have means to instantiate it statically in
>>> arm virt memory map?
>>
>> /me neither
>>
>> in previous version there was a machine option to enable the feature
>> to that was rejected in favor of device.
>>
>> in this case for platform -device of sysbus based device, I don't think
>> we can do better that dynamic sysbus.
>
> sorry I may have missed some previous discussion details. As far as I
> can read, I understand you could instantiate the wdt in a free MMIO
> slot, unconfitionnaly just as it is done in hw/arm/sbsa-ref.c. Maybe add
> a compat to avoid having it by default on older machine types. Then
> about the type of the integration gtdt or wat, can't you have a device
> compat?
After further reading of the previous version thread, I wonder if you
shouldn't always instantiate the watchdog in the machine instead.
Add a device property allowing to switch between GWDT or WDAT version.
In arm virt,
1) if you discover the GWDT version is selected (default) you generate
both dt and GTDT ACPI table
2) if you discover the WDAT version is selected, you only generate WDAT
ACPI description and you output an error in case of DT boot.
You may add a machine no_wdt flag to handle compats for older machine
types if needed.
Would that make sense?
Otherwise, can you point me the msgid where the -device was prefered?
Thanks
Eric
>
> Thanks
>
> Eric
>
>>
>>
>>>
>>> Eric
>>>>
>>>> Tested with Fedora 43:
>>>> FDT: -M virt,acpi=off -device sbsa_gwdt
>>>> ACPI: -M virt -device sbsa_gwdt
>>>>
>>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>>>> ---
>>>> hw/arm/Kconfig | 1 +
>>>> hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
>>>> hw/arm/virt.c | 2 ++
>>>> hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
>>>> hw/watchdog/sbsa_gwdt.c | 1 +
>>>> 5 files changed, 67 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>>>> index c66c452737..1222efadd1 100644
>>>> --- a/hw/arm/Kconfig
>>>> +++ b/hw/arm/Kconfig
>>>> @@ -36,6 +36,7 @@ config ARM_VIRT
>>>> select VIRTIO_MEM_SUPPORTED
>>>> select ACPI_CXL
>>>> select ACPI_HMAT
>>>> + select WDT_SBSA
>>>>
>>>> config CUBIEBOARD
>>>> bool
>>>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>>>> index 719d2f994e..9c14b1d4d5 100644
>>>> --- a/hw/arm/virt-acpi-build.c
>>>> +++ b/hw/arm/virt-acpi-build.c
>>>> @@ -64,6 +64,7 @@
>>>> #include "hw/virtio/virtio-acpi.h"
>>>> #include "target/arm/cpu.h"
>>>> #include "target/arm/multiprocessing.h"
>>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>>
>>>> #define ARM_SPI_BASE 32
>>>>
>>>> @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>> const uint32_t irqflags = 0; /* Interrupt is Level triggered */
>>>> AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
>>>> .oem_table_id = vms->oem_table_id };
>>>> + uint32_t gtdt_start = table_data->len;
>>>> + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
>>>>
>>>> acpi_table_begin(&table, table_data);
>>>>
>>>> @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>> build_append_int_noprefix(table_data, irqflags, 4);
>>>> /* CntReadBase Physical address */
>>>> build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
>>>> +
>>>> /* Platform Timer Count */
>>>> - build_append_int_noprefix(table_data, 0, 4);
>>>> + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
>>>> /* Platform Timer Offset */
>>>> - build_append_int_noprefix(table_data, 0, 4);
>>>> + build_append_int_noprefix(table_data,
>>>> + wdt ? (table_data->len - gtdt_start) +
>>>> + 4 + 4 + 4 /* len of this & following 2 fields to skip */
>>>> + : 0, 4);
>>>> +
>>>> if (vms->ns_el2_virt_timer_irq) {
>>>> /* Virtual EL2 Timer GSIV */
>>>> build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
>>>> @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>> build_append_int_noprefix(table_data, 0, 4);
>>>> build_append_int_noprefix(table_data, 0, 4);
>>>> }
>>>> +
>>>> + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
>>>> + if (wdt) {
>>>> + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
>>>> + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
>>>> + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
>>>> + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
>>>> + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
>>>> + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
>>>> + platform_bus_get_irqn(pbus, sd, 0);
>>>> +
>>>> + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
>>>> + build_append_int_noprefix(table_data, 28 /* Length */, 2);
>>>> + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
>>>> + /* RefreshFrame Physical Address */
>>>> + build_append_int_noprefix(table_data, rbase, 8);
>>>> + /* WatchdogControlFrame Physical Address */
>>>> + build_append_int_noprefix(table_data, cbase, 8);
>>>> + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
>>>> + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
>>>> + }
>>>> acpi_table_end(linker, &table);
>>>> }
>>>>
>>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>>>> index cab2e21e8a..a87991b591 100644
>>>> --- a/hw/arm/virt.c
>>>> +++ b/hw/arm/virt.c
>>>> @@ -95,6 +95,7 @@
>>>> #include "hw/cxl/cxl.h"
>>>> #include "hw/cxl/cxl_host.h"
>>>> #include "qemu/guest-random.h"
>>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>>
>>>> static GlobalProperty arm_virt_compat_defaults[] = {
>>>> { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
>>>> @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
>>>> + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
>>>> #ifdef CONFIG_TPM
>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
>>>> #endif
>>>> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
>>>> index 89d0c46445..76aa1bc579 100644
>>>> --- a/hw/core/sysbus-fdt.c
>>>> +++ b/hw/core/sysbus-fdt.c
>>>> @@ -36,6 +36,7 @@
>>>> #include "hw/display/ramfb.h"
>>>> #include "hw/uefi/var-service-api.h"
>>>> #include "hw/arm/fdt.h"
>>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>>
>>>> /*
>>>> * internal struct that contains the information to create dynamic
>>>> @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
>>>> return 0;
>>>> }
>>>>
>>>> +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
>>>> +{
>>>> + PlatformBusFDTData *data = opaque;
>>>> + PlatformBusDevice *pbus = data->pbus;
>>>> + const char *parent_node = data->pbus_node_name;
>>>> + void *fdt = data->fdt;
>>>> + uint64_t cbase, rbase;
>>>> + char *nodename;
>>>> + int irq;
>>>> +
>>>> + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
>>>> + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
>>>> + irq = platform_bus_get_irqn(pbus, sbdev, 0);
>>>> +
>>>> + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
>>>> + qemu_fdt_add_subnode(fdt, nodename);
>>>> +
>>>> + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
>>>> + qemu_fdt_setprop_cells(fdt, nodename, "reg",
>>>> + cbase, SBSA_GWDT_CMMIO_SIZE,
>>>> + rbase, SBSA_GWDT_RMMIO_SIZE);
>>>> + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
>>>> + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
>>>> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>>>> + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
>>>> +
>>>> + g_free(nodename);
>>>> + return 0;
>>>> +}
>>>> +
>>>> static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
>>>> {
>>>> return 0;
>>>> @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
>>>> TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
>>>> TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
>>>> TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
>>>> + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
>>>> TYPE_BINDING("", NULL), /* last element */
>>>> };
>>>>
>>>> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
>>>> index acb970e8b3..c4dd8005b7 100644
>>>> --- a/hw/watchdog/sbsa_gwdt.c
>>>> +++ b/hw/watchdog/sbsa_gwdt.c
>>>> @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
>>>> dc->realize = wdt_sbsa_gwdt_realize;
>>>> device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
>>>> dc->hotpluggable = false;
>>>> + dc->user_creatable = true;
>>>> set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
>>>> dc->vmsd = &vmstate_sbsa_gwdt;
>>>> dc->desc = "SBSA-compliant generic watchdog device";
>>>
>>
>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-05-28 9:59 ` Eric Auger
@ 2026-05-28 14:37 ` Igor Mammedov
2026-06-01 16:37 ` Eric Auger
0 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-05-28 14:37 UTC (permalink / raw)
To: Eric Auger
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm,
Daniel P. Berrangé, Markus Armbruster
On Thu, 28 May 2026 11:59:06 +0200
Eric Auger <eauger@redhat.com> wrote:
> Hi,
>
> On 5/28/26 11:04 AM, Eric Auger wrote:
> > Hi Igor,
> >
> > On 5/27/26 2:49 PM, Igor Mammedov wrote:
> >> On Tue, 26 May 2026 15:58:08 +0200
> >> Eric Auger <eauger@redhat.com> wrote:
> >>
> >>> Hi Igor,
> >>>
> >>> On 3/3/26 10:25 AM, Igor Mammedov wrote:
> >>>> Allow to use SBSA generic watchdog with virt machine type.
> >>>> (includes conditional generation of corresponding FDT and
> >>>> ACPI GTDT descriptors)
> >>>>
> >>>> Use '-device sbsa_gwdt' to command line to enable it.
> >>> I thank that in general Peter is not a big fan of dynamic instantiation
> >>> of sysbus devices. Don't you have means to instantiate it statically in
> >>> arm virt memory map?
On Peter's part, there weren't any objection to the idea using -device.
(neither in v1 nor in this revision).
> >> /me neither
> >>
> >> in previous version there was a machine option to enable the feature
> >> to that was rejected in favor of device.
> >>
> >> in this case for platform -device of sysbus based device, I don't think
> >> we can do better that dynamic sysbus.
> >
> > sorry I may have missed some previous discussion details. As far as I
> > can read, I understand you could instantiate the wdt in a free MMIO
> > slot, unconfitionnaly just as it is done in hw/arm/sbsa-ref.c. Maybe add
> > a compat to avoid having it by default on older machine types. Then
> > about the type of the integration gtdt or wat, can't you have a device
> > compat?
> After further reading of the previous version thread, I wonder if you
> shouldn't always instantiate the watchdog in the machine instead.
>
> Add a device property allowing to switch between GWDT or WDAT version.
>
> In arm virt,
>
> 1) if you discover the GWDT version is selected (default) you generate
> both dt and GTDT ACPI table
> 2) if you discover the WDAT version is selected, you only generate WDAT
> ACPI description and you output an error in case of DT boot.
>
> You may add a machine no_wdt flag to handle compats for older machine
> types if needed.
rereading v1 thread it seems that there weren't much objection to adding
a dedicated virt machine property to enable 'wdat' [1] /like what is done to q35/.
problem was in conflating too generic whatchdog=none/auto/native/acpi into
one knob and discussion quickly went down rabbit hole of semantics.
For Q35, we don't really have a choice as it's already builtin device,
but for arm/virt we can do better than a bunch of compats and proxy
properties. (as Markus noted in v1 review, we've done that/still do
but it doesn't scale well)
I can go old route and revert to simplified v1 that would:
* make gwdt builtin device on arm/virt board
(i.e. default to SBSA native watchdog with GTDT ACPI table
and relevant FDT entries)
* add a machine.gwdt-wdat=on|off property
1. that will make gwdt to use 1KHz frequency
2. enable WDAT ACPI table
3. disable GTDT ACPI table and relevant FDT entries
as they are mutually exclusive with #1 point
* add a compat knob to disable gwdt on old machine types.
Re-spinning that wouldn't take much effort, all the code already exist,
just needs mostly reshuffling.
1) I think Daniel was ok having something like gwdt-wdat=on|off
from libvirt pov.
That said,
Having watchdog as an optional -device is much cleaner compared to
adding knobs to machine (both internal compats and external to enable
specific watchdog).
Good (well bad actualy) example of compats/props is set of
ITS ones, one eventually can untangle what depends on what
and how that works together, but I'd rather avoid doing that.
Perhaps I went overboard with move to -device.
Anyways, all I can do is suggest in my opinion a better way,
but it's upto arm folks to pick a preferred approach.
> Would that make sense?
>
> Otherwise, can you point me the msgid where the -device was prefered?
Sorry, rereading v1 thread, -device was just an idea to try
(but by no means a preferred/consensus one).
>
> Thanks
>
> Eric
> >
> > Thanks
> >
> > Eric
> >
> >>
> >>
> >>>
> >>> Eric
> >>>>
> >>>> Tested with Fedora 43:
> >>>> FDT: -M virt,acpi=off -device sbsa_gwdt
> >>>> ACPI: -M virt -device sbsa_gwdt
> >>>>
> >>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> >>>> ---
> >>>> hw/arm/Kconfig | 1 +
> >>>> hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
> >>>> hw/arm/virt.c | 2 ++
> >>>> hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
> >>>> hw/watchdog/sbsa_gwdt.c | 1 +
> >>>> 5 files changed, 67 insertions(+), 2 deletions(-)
> >>>>
> >>>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> >>>> index c66c452737..1222efadd1 100644
> >>>> --- a/hw/arm/Kconfig
> >>>> +++ b/hw/arm/Kconfig
> >>>> @@ -36,6 +36,7 @@ config ARM_VIRT
> >>>> select VIRTIO_MEM_SUPPORTED
> >>>> select ACPI_CXL
> >>>> select ACPI_HMAT
> >>>> + select WDT_SBSA
> >>>>
> >>>> config CUBIEBOARD
> >>>> bool
> >>>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> >>>> index 719d2f994e..9c14b1d4d5 100644
> >>>> --- a/hw/arm/virt-acpi-build.c
> >>>> +++ b/hw/arm/virt-acpi-build.c
> >>>> @@ -64,6 +64,7 @@
> >>>> #include "hw/virtio/virtio-acpi.h"
> >>>> #include "target/arm/cpu.h"
> >>>> #include "target/arm/multiprocessing.h"
> >>>> +#include "hw/watchdog/sbsa_gwdt.h"
> >>>>
> >>>> #define ARM_SPI_BASE 32
> >>>>
> >>>> @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >>>> const uint32_t irqflags = 0; /* Interrupt is Level triggered */
> >>>> AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
> >>>> .oem_table_id = vms->oem_table_id };
> >>>> + uint32_t gtdt_start = table_data->len;
> >>>> + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
> >>>>
> >>>> acpi_table_begin(&table, table_data);
> >>>>
> >>>> @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >>>> build_append_int_noprefix(table_data, irqflags, 4);
> >>>> /* CntReadBase Physical address */
> >>>> build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
> >>>> +
> >>>> /* Platform Timer Count */
> >>>> - build_append_int_noprefix(table_data, 0, 4);
> >>>> + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
> >>>> /* Platform Timer Offset */
> >>>> - build_append_int_noprefix(table_data, 0, 4);
> >>>> + build_append_int_noprefix(table_data,
> >>>> + wdt ? (table_data->len - gtdt_start) +
> >>>> + 4 + 4 + 4 /* len of this & following 2 fields to skip */
> >>>> + : 0, 4);
> >>>> +
> >>>> if (vms->ns_el2_virt_timer_irq) {
> >>>> /* Virtual EL2 Timer GSIV */
> >>>> build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
> >>>> @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >>>> build_append_int_noprefix(table_data, 0, 4);
> >>>> build_append_int_noprefix(table_data, 0, 4);
> >>>> }
> >>>> +
> >>>> + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
> >>>> + if (wdt) {
> >>>> + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> >>>> + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
> >>>> + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> >>>> + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
> >>>> + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
> >>>> + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
> >>>> + platform_bus_get_irqn(pbus, sd, 0);
> >>>> +
> >>>> + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
> >>>> + build_append_int_noprefix(table_data, 28 /* Length */, 2);
> >>>> + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
> >>>> + /* RefreshFrame Physical Address */
> >>>> + build_append_int_noprefix(table_data, rbase, 8);
> >>>> + /* WatchdogControlFrame Physical Address */
> >>>> + build_append_int_noprefix(table_data, cbase, 8);
> >>>> + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
> >>>> + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
> >>>> + }
> >>>> acpi_table_end(linker, &table);
> >>>> }
> >>>>
> >>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> >>>> index cab2e21e8a..a87991b591 100644
> >>>> --- a/hw/arm/virt.c
> >>>> +++ b/hw/arm/virt.c
> >>>> @@ -95,6 +95,7 @@
> >>>> #include "hw/cxl/cxl.h"
> >>>> #include "hw/cxl/cxl_host.h"
> >>>> #include "qemu/guest-random.h"
> >>>> +#include "hw/watchdog/sbsa_gwdt.h"
> >>>>
> >>>> static GlobalProperty arm_virt_compat_defaults[] = {
> >>>> { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
> >>>> @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
> >>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> >>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
> >>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
> >>>> + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
> >>>> #ifdef CONFIG_TPM
> >>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> >>>> #endif
> >>>> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> >>>> index 89d0c46445..76aa1bc579 100644
> >>>> --- a/hw/core/sysbus-fdt.c
> >>>> +++ b/hw/core/sysbus-fdt.c
> >>>> @@ -36,6 +36,7 @@
> >>>> #include "hw/display/ramfb.h"
> >>>> #include "hw/uefi/var-service-api.h"
> >>>> #include "hw/arm/fdt.h"
> >>>> +#include "hw/watchdog/sbsa_gwdt.h"
> >>>>
> >>>> /*
> >>>> * internal struct that contains the information to create dynamic
> >>>> @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
> >>>> return 0;
> >>>> }
> >>>>
> >>>> +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
> >>>> +{
> >>>> + PlatformBusFDTData *data = opaque;
> >>>> + PlatformBusDevice *pbus = data->pbus;
> >>>> + const char *parent_node = data->pbus_node_name;
> >>>> + void *fdt = data->fdt;
> >>>> + uint64_t cbase, rbase;
> >>>> + char *nodename;
> >>>> + int irq;
> >>>> +
> >>>> + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
> >>>> + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
> >>>> + irq = platform_bus_get_irqn(pbus, sbdev, 0);
> >>>> +
> >>>> + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
> >>>> + qemu_fdt_add_subnode(fdt, nodename);
> >>>> +
> >>>> + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
> >>>> + qemu_fdt_setprop_cells(fdt, nodename, "reg",
> >>>> + cbase, SBSA_GWDT_CMMIO_SIZE,
> >>>> + rbase, SBSA_GWDT_RMMIO_SIZE);
> >>>> + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
> >>>> + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
> >>>> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> >>>> + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
> >>>> +
> >>>> + g_free(nodename);
> >>>> + return 0;
> >>>> +}
> >>>> +
> >>>> static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
> >>>> {
> >>>> return 0;
> >>>> @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
> >>>> TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
> >>>> TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
> >>>> TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
> >>>> + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
> >>>> TYPE_BINDING("", NULL), /* last element */
> >>>> };
> >>>>
> >>>> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> >>>> index acb970e8b3..c4dd8005b7 100644
> >>>> --- a/hw/watchdog/sbsa_gwdt.c
> >>>> +++ b/hw/watchdog/sbsa_gwdt.c
> >>>> @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
> >>>> dc->realize = wdt_sbsa_gwdt_realize;
> >>>> device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
> >>>> dc->hotpluggable = false;
> >>>> + dc->user_creatable = true;
> >>>> set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
> >>>> dc->vmsd = &vmstate_sbsa_gwdt;
> >>>> dc->desc = "SBSA-compliant generic watchdog device";
> >>>
> >>
> >
>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-05-28 14:37 ` Igor Mammedov
@ 2026-06-01 16:37 ` Eric Auger
2026-06-02 12:41 ` Igor Mammedov
0 siblings, 1 reply; 57+ messages in thread
From: Eric Auger @ 2026-06-01 16:37 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm,
Daniel P. Berrangé, Markus Armbruster
Hi Igor,
On 5/28/26 4:37 PM, Igor Mammedov wrote:
> On Thu, 28 May 2026 11:59:06 +0200
> Eric Auger <eauger@redhat.com> wrote:
>
>> Hi,
>>
>> On 5/28/26 11:04 AM, Eric Auger wrote:
>>> Hi Igor,
>>>
>>> On 5/27/26 2:49 PM, Igor Mammedov wrote:
>>>> On Tue, 26 May 2026 15:58:08 +0200
>>>> Eric Auger <eauger@redhat.com> wrote:
>>>>
>>>>> Hi Igor,
>>>>>
>>>>> On 3/3/26 10:25 AM, Igor Mammedov wrote:
>>>>>> Allow to use SBSA generic watchdog with virt machine type.
>>>>>> (includes conditional generation of corresponding FDT and
>>>>>> ACPI GTDT descriptors)
>>>>>>
>>>>>> Use '-device sbsa_gwdt' to command line to enable it.
>>>>> I thank that in general Peter is not a big fan of dynamic instantiation
>>>>> of sysbus devices. Don't you have means to instantiate it statically in
>>>>> arm virt memory map?
>
> On Peter's part, there weren't any objection to the idea using -device.
> (neither in v1 nor in this revision).
>
>
>>>> /me neither
>>>>
>>>> in previous version there was a machine option to enable the feature
>>>> to that was rejected in favor of device.
>>>>
>>>> in this case for platform -device of sysbus based device, I don't think
>>>> we can do better that dynamic sysbus.
>>>
>>> sorry I may have missed some previous discussion details. As far as I
>>> can read, I understand you could instantiate the wdt in a free MMIO
>>> slot, unconfitionnaly just as it is done in hw/arm/sbsa-ref.c. Maybe add
>>> a compat to avoid having it by default on older machine types. Then
>>> about the type of the integration gtdt or wat, can't you have a device
>>> compat?
>> After further reading of the previous version thread, I wonder if you
>> shouldn't always instantiate the watchdog in the machine instead.
>>
>> Add a device property allowing to switch between GWDT or WDAT version.
>>
>> In arm virt,
>>
>> 1) if you discover the GWDT version is selected (default) you generate
>> both dt and GTDT ACPI table
>> 2) if you discover the WDAT version is selected, you only generate WDAT
>> ACPI description and you output an error in case of DT boot.
>>
>> You may add a machine no_wdt flag to handle compats for older machine
>> types if needed.
>
> rereading v1 thread it seems that there weren't much objection to adding
> a dedicated virt machine property to enable 'wdat' [1] /like what is done to q35/.
>
> problem was in conflating too generic whatchdog=none/auto/native/acpi into
> one knob and discussion quickly went down rabbit hole of semantics.
>
> For Q35, we don't really have a choice as it's already builtin device,
> but for arm/virt we can do better than a bunch of compats and proxy
> properties. (as Markus noted in v1 review, we've done that/still do
> but it doesn't scale well)
>
> I can go old route and revert to simplified v1 that would:
> * make gwdt builtin device on arm/virt board
> (i.e. default to SBSA native watchdog with GTDT ACPI table
> and relevant FDT entries)
would make sense to me.
> * add a machine.gwdt-wdat=on|off property
> 1. that will make gwdt to use 1KHz frequency
> 2. enable WDAT ACPI table
> 3. disable GTDT ACPI table and relevant FDT entries
> as they are mutually exclusive with #1 point
> * add a compat knob to disable gwdt on old machine types.
Either that or device prop setting as we have for ACPI PCI HP (technique
you advocated at some point).
>
> Re-spinning that wouldn't take much effort, all the code already exist,
> just needs mostly reshuffling.
>
> 1) I think Daniel was ok having something like gwdt-wdat=on|off
> from libvirt pov.
>
> That said,
> Having watchdog as an optional -device is much cleaner compared to
> adding knobs to machine (both internal compats and external to enable
> specific watchdog).
I am OK with that too. However in general I think Peter prefers having
them statically instantiated if possible. All the more so I think that
having a watchdog, always instantiated, in its GTDT/FDT form (not WDAT
ACPI only) in machvirt would make sense in general and does not make
much trouble in terms of MMIO layout.> Good (well bad actualy) example
of compats/props is set of
> ITS ones, one eventually can untangle what depends on what
> and how that works together, but I'd rather avoid doing that.
>
> Perhaps I went overboard with move to -device.
> Anyways, all I can do is suggest in my opinion a better way,
> but it's upto arm folks to pick a preferred approach.
>
>> Would that make sense?
>>
>> Otherwise, can you point me the msgid where the -device was prefered?
> Sorry, rereading v1 thread, -device was just an idea to try
> (but by no means a preferred/consensus one).
This is what I understood too.
Thanks
Eric
>
>>
>> Thanks
>>
>> Eric
>>>
>>> Thanks
>>>
>>> Eric
>>>
>>>>
>>>>
>>>>>
>>>>> Eric
>>>>>>
>>>>>> Tested with Fedora 43:
>>>>>> FDT: -M virt,acpi=off -device sbsa_gwdt
>>>>>> ACPI: -M virt -device sbsa_gwdt
>>>>>>
>>>>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>>>>>> ---
>>>>>> hw/arm/Kconfig | 1 +
>>>>>> hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
>>>>>> hw/arm/virt.c | 2 ++
>>>>>> hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
>>>>>> hw/watchdog/sbsa_gwdt.c | 1 +
>>>>>> 5 files changed, 67 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>>>>>> index c66c452737..1222efadd1 100644
>>>>>> --- a/hw/arm/Kconfig
>>>>>> +++ b/hw/arm/Kconfig
>>>>>> @@ -36,6 +36,7 @@ config ARM_VIRT
>>>>>> select VIRTIO_MEM_SUPPORTED
>>>>>> select ACPI_CXL
>>>>>> select ACPI_HMAT
>>>>>> + select WDT_SBSA
>>>>>>
>>>>>> config CUBIEBOARD
>>>>>> bool
>>>>>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>>>>>> index 719d2f994e..9c14b1d4d5 100644
>>>>>> --- a/hw/arm/virt-acpi-build.c
>>>>>> +++ b/hw/arm/virt-acpi-build.c
>>>>>> @@ -64,6 +64,7 @@
>>>>>> #include "hw/virtio/virtio-acpi.h"
>>>>>> #include "target/arm/cpu.h"
>>>>>> #include "target/arm/multiprocessing.h"
>>>>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>>>>
>>>>>> #define ARM_SPI_BASE 32
>>>>>>
>>>>>> @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>>>> const uint32_t irqflags = 0; /* Interrupt is Level triggered */
>>>>>> AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
>>>>>> .oem_table_id = vms->oem_table_id };
>>>>>> + uint32_t gtdt_start = table_data->len;
>>>>>> + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
>>>>>>
>>>>>> acpi_table_begin(&table, table_data);
>>>>>>
>>>>>> @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>>>> build_append_int_noprefix(table_data, irqflags, 4);
>>>>>> /* CntReadBase Physical address */
>>>>>> build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
>>>>>> +
>>>>>> /* Platform Timer Count */
>>>>>> - build_append_int_noprefix(table_data, 0, 4);
>>>>>> + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
>>>>>> /* Platform Timer Offset */
>>>>>> - build_append_int_noprefix(table_data, 0, 4);
>>>>>> + build_append_int_noprefix(table_data,
>>>>>> + wdt ? (table_data->len - gtdt_start) +
>>>>>> + 4 + 4 + 4 /* len of this & following 2 fields to skip */
>>>>>> + : 0, 4);
>>>>>> +
>>>>>> if (vms->ns_el2_virt_timer_irq) {
>>>>>> /* Virtual EL2 Timer GSIV */
>>>>>> build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
>>>>>> @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>>>> build_append_int_noprefix(table_data, 0, 4);
>>>>>> build_append_int_noprefix(table_data, 0, 4);
>>>>>> }
>>>>>> +
>>>>>> + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
>>>>>> + if (wdt) {
>>>>>> + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
>>>>>> + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
>>>>>> + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
>>>>>> + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
>>>>>> + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
>>>>>> + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
>>>>>> + platform_bus_get_irqn(pbus, sd, 0);
>>>>>> +
>>>>>> + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
>>>>>> + build_append_int_noprefix(table_data, 28 /* Length */, 2);
>>>>>> + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
>>>>>> + /* RefreshFrame Physical Address */
>>>>>> + build_append_int_noprefix(table_data, rbase, 8);
>>>>>> + /* WatchdogControlFrame Physical Address */
>>>>>> + build_append_int_noprefix(table_data, cbase, 8);
>>>>>> + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
>>>>>> + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
>>>>>> + }
>>>>>> acpi_table_end(linker, &table);
>>>>>> }
>>>>>>
>>>>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>>>>>> index cab2e21e8a..a87991b591 100644
>>>>>> --- a/hw/arm/virt.c
>>>>>> +++ b/hw/arm/virt.c
>>>>>> @@ -95,6 +95,7 @@
>>>>>> #include "hw/cxl/cxl.h"
>>>>>> #include "hw/cxl/cxl_host.h"
>>>>>> #include "qemu/guest-random.h"
>>>>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>>>>
>>>>>> static GlobalProperty arm_virt_compat_defaults[] = {
>>>>>> { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
>>>>>> @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
>>>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>>>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
>>>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
>>>>>> + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
>>>>>> #ifdef CONFIG_TPM
>>>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
>>>>>> #endif
>>>>>> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
>>>>>> index 89d0c46445..76aa1bc579 100644
>>>>>> --- a/hw/core/sysbus-fdt.c
>>>>>> +++ b/hw/core/sysbus-fdt.c
>>>>>> @@ -36,6 +36,7 @@
>>>>>> #include "hw/display/ramfb.h"
>>>>>> #include "hw/uefi/var-service-api.h"
>>>>>> #include "hw/arm/fdt.h"
>>>>>> +#include "hw/watchdog/sbsa_gwdt.h"
>>>>>>
>>>>>> /*
>>>>>> * internal struct that contains the information to create dynamic
>>>>>> @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
>>>>>> return 0;
>>>>>> }
>>>>>>
>>>>>> +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
>>>>>> +{
>>>>>> + PlatformBusFDTData *data = opaque;
>>>>>> + PlatformBusDevice *pbus = data->pbus;
>>>>>> + const char *parent_node = data->pbus_node_name;
>>>>>> + void *fdt = data->fdt;
>>>>>> + uint64_t cbase, rbase;
>>>>>> + char *nodename;
>>>>>> + int irq;
>>>>>> +
>>>>>> + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
>>>>>> + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
>>>>>> + irq = platform_bus_get_irqn(pbus, sbdev, 0);
>>>>>> +
>>>>>> + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
>>>>>> + qemu_fdt_add_subnode(fdt, nodename);
>>>>>> +
>>>>>> + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
>>>>>> + qemu_fdt_setprop_cells(fdt, nodename, "reg",
>>>>>> + cbase, SBSA_GWDT_CMMIO_SIZE,
>>>>>> + rbase, SBSA_GWDT_RMMIO_SIZE);
>>>>>> + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
>>>>>> + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
>>>>>> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>>>>>> + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
>>>>>> +
>>>>>> + g_free(nodename);
>>>>>> + return 0;
>>>>>> +}
>>>>>> +
>>>>>> static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
>>>>>> {
>>>>>> return 0;
>>>>>> @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
>>>>>> TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
>>>>>> TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
>>>>>> TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
>>>>>> + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
>>>>>> TYPE_BINDING("", NULL), /* last element */
>>>>>> };
>>>>>>
>>>>>> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
>>>>>> index acb970e8b3..c4dd8005b7 100644
>>>>>> --- a/hw/watchdog/sbsa_gwdt.c
>>>>>> +++ b/hw/watchdog/sbsa_gwdt.c
>>>>>> @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
>>>>>> dc->realize = wdt_sbsa_gwdt_realize;
>>>>>> device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
>>>>>> dc->hotpluggable = false;
>>>>>> + dc->user_creatable = true;
>>>>>> set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
>>>>>> dc->vmsd = &vmstate_sbsa_gwdt;
>>>>>> dc->desc = "SBSA-compliant generic watchdog device";
>>>>>
>>>>
>>>
>>
>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-06-01 16:37 ` Eric Auger
@ 2026-06-02 12:41 ` Igor Mammedov
0 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-06-02 12:41 UTC (permalink / raw)
To: Eric Auger
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm,
Daniel P. Berrangé, Markus Armbruster
On Mon, 1 Jun 2026 18:37:05 +0200
Eric Auger <eauger@redhat.com> wrote:
> Hi Igor,
>
> On 5/28/26 4:37 PM, Igor Mammedov wrote:
> > On Thu, 28 May 2026 11:59:06 +0200
> > Eric Auger <eauger@redhat.com> wrote:
> >
> >> Hi,
> >>
> >> On 5/28/26 11:04 AM, Eric Auger wrote:
> >>> Hi Igor,
> >>>
> >>> On 5/27/26 2:49 PM, Igor Mammedov wrote:
> >>>> On Tue, 26 May 2026 15:58:08 +0200
> >>>> Eric Auger <eauger@redhat.com> wrote:
> >>>>
> >>>>> Hi Igor,
> >>>>>
> >>>>> On 3/3/26 10:25 AM, Igor Mammedov wrote:
> >>>>>> Allow to use SBSA generic watchdog with virt machine type.
> >>>>>> (includes conditional generation of corresponding FDT and
> >>>>>> ACPI GTDT descriptors)
> >>>>>>
> >>>>>> Use '-device sbsa_gwdt' to command line to enable it.
> >>>>> I thank that in general Peter is not a big fan of dynamic instantiation
> >>>>> of sysbus devices. Don't you have means to instantiate it statically in
> >>>>> arm virt memory map?
> >
> > On Peter's part, there weren't any objection to the idea using -device.
> > (neither in v1 nor in this revision).
> >
> >
> >>>> /me neither
> >>>>
> >>>> in previous version there was a machine option to enable the feature
> >>>> to that was rejected in favor of device.
> >>>>
> >>>> in this case for platform -device of sysbus based device, I don't think
> >>>> we can do better that dynamic sysbus.
> >>>
> >>> sorry I may have missed some previous discussion details. As far as I
> >>> can read, I understand you could instantiate the wdt in a free MMIO
> >>> slot, unconfitionnaly just as it is done in hw/arm/sbsa-ref.c. Maybe add
> >>> a compat to avoid having it by default on older machine types. Then
> >>> about the type of the integration gtdt or wat, can't you have a device
> >>> compat?
> >> After further reading of the previous version thread, I wonder if you
> >> shouldn't always instantiate the watchdog in the machine instead.
> >>
> >> Add a device property allowing to switch between GWDT or WDAT version.
> >>
> >> In arm virt,
> >>
> >> 1) if you discover the GWDT version is selected (default) you generate
> >> both dt and GTDT ACPI table
> >> 2) if you discover the WDAT version is selected, you only generate WDAT
> >> ACPI description and you output an error in case of DT boot.
> >>
> >> You may add a machine no_wdt flag to handle compats for older machine
> >> types if needed.
> >
> > rereading v1 thread it seems that there weren't much objection to adding
> > a dedicated virt machine property to enable 'wdat' [1] /like what is done to q35/.
> >
> > problem was in conflating too generic whatchdog=none/auto/native/acpi into
> > one knob and discussion quickly went down rabbit hole of semantics.
> >
> > For Q35, we don't really have a choice as it's already builtin device,
> > but for arm/virt we can do better than a bunch of compats and proxy
> > properties. (as Markus noted in v1 review, we've done that/still do
> > but it doesn't scale well)
> >
> > I can go old route and revert to simplified v1 that would:
> > * make gwdt builtin device on arm/virt board
> > (i.e. default to SBSA native watchdog with GTDT ACPI table
> > and relevant FDT entries)
> would make sense to me.
forgot about why it's not default ATM,
the reason being that native/default GWDT causes issues on Windows
(only WDAT variant works).
the last 2 patches trying to do some damage control,
but what we can do on qemu side is limited.
and builtin gwdt we would end up with a mess of gwdt=on|of and wdat=o|n,
So I'd rather have watchdog as an optional device included to VM
when asked by user.
With side benefit reducing attack surface when device is not
needed compared to built-in by default variant.
> > * add a machine.gwdt-wdat=on|off property
> > 1. that will make gwdt to use 1KHz frequency
> > 2. enable WDAT ACPI table
> > 3. disable GTDT ACPI table and relevant FDT entries
> > as they are mutually exclusive with #1 point
> > * add a compat knob to disable gwdt on old machine types.
> Either that or device prop setting as we have for ACPI PCI HP (technique
> you advocated at some point).
that was for symmetry with existing acpi pci hp feature on x86 if I recall
correctly. There is no much options for builtin devices, we either
* use -global to tweak them (historical variant)
* more recent trend is proxy property in -machine
both not great variants, I've tried in v1 to propose generic
-machine watchdog=foo to at least limit a zoo of options, but that was rejected.
> >
> > Re-spinning that wouldn't take much effort, all the code already exist,
> > just needs mostly reshuffling.
> >
> > 1) I think Daniel was ok having something like gwdt-wdat=on|off
> > from libvirt pov.
> >
> > That said,
> > Having watchdog as an optional -device is much cleaner compared to
> > adding knobs to machine (both internal compats and external to enable
> > specific watchdog).
> I am OK with that too. However in general I think Peter prefers having
> them statically instantiated if possible. All the more so I think that
> having a watchdog, always instantiated, in its GTDT/FDT form (not WDAT
> ACPI only) in machvirt would make sense in general and does not make
> much trouble in terms of MMIO layout.
If there is no objections, lets go with -device variant
If dynamic sysbus resources is of concern, I probably can pin/make them
static, using device plug handler (virt_machine_device_plug_cb).
Let me try and see what could be done wrt static resources.
At this point series needs a rebase, due to conflicts.
So I'll respin it with staic variant if it works out or as it's now.
But while I'm at it, pls review the remaining not reviewed yet patches,
as they aren't likely to change. Especially generic GWDT fixes 18-21/21.
> Good (well bad actualy) example
> of compats/props is set of
> > ITS ones, one eventually can untangle what depends on what
> > and how that works together, but I'd rather avoid doing that.
> >
> > Perhaps I went overboard with move to -device.
> > Anyways, all I can do is suggest in my opinion a better way,
> > but it's upto arm folks to pick a preferred approach.
> >
> >> Would that make sense?
> >>
> >> Otherwise, can you point me the msgid where the -device was prefered?
> > Sorry, rereading v1 thread, -device was just an idea to try
> > (but by no means a preferred/consensus one).
> This is what I understood too.
>
> Thanks
>
> Eric
> >
> >>
> >> Thanks
> >>
> >> Eric
> >>>
> >>> Thanks
> >>>
> >>> Eric
> >>>
> >>>>
> >>>>
> >>>>>
> >>>>> Eric
> >>>>>>
> >>>>>> Tested with Fedora 43:
> >>>>>> FDT: -M virt,acpi=off -device sbsa_gwdt
> >>>>>> ACPI: -M virt -device sbsa_gwdt
> >>>>>>
> >>>>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> >>>>>> ---
> >>>>>> hw/arm/Kconfig | 1 +
> >>>>>> hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
> >>>>>> hw/arm/virt.c | 2 ++
> >>>>>> hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
> >>>>>> hw/watchdog/sbsa_gwdt.c | 1 +
> >>>>>> 5 files changed, 67 insertions(+), 2 deletions(-)
> >>>>>>
> >>>>>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> >>>>>> index c66c452737..1222efadd1 100644
> >>>>>> --- a/hw/arm/Kconfig
> >>>>>> +++ b/hw/arm/Kconfig
> >>>>>> @@ -36,6 +36,7 @@ config ARM_VIRT
> >>>>>> select VIRTIO_MEM_SUPPORTED
> >>>>>> select ACPI_CXL
> >>>>>> select ACPI_HMAT
> >>>>>> + select WDT_SBSA
> >>>>>>
> >>>>>> config CUBIEBOARD
> >>>>>> bool
> >>>>>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> >>>>>> index 719d2f994e..9c14b1d4d5 100644
> >>>>>> --- a/hw/arm/virt-acpi-build.c
> >>>>>> +++ b/hw/arm/virt-acpi-build.c
> >>>>>> @@ -64,6 +64,7 @@
> >>>>>> #include "hw/virtio/virtio-acpi.h"
> >>>>>> #include "target/arm/cpu.h"
> >>>>>> #include "target/arm/multiprocessing.h"
> >>>>>> +#include "hw/watchdog/sbsa_gwdt.h"
> >>>>>>
> >>>>>> #define ARM_SPI_BASE 32
> >>>>>>
> >>>>>> @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >>>>>> const uint32_t irqflags = 0; /* Interrupt is Level triggered */
> >>>>>> AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
> >>>>>> .oem_table_id = vms->oem_table_id };
> >>>>>> + uint32_t gtdt_start = table_data->len;
> >>>>>> + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
> >>>>>>
> >>>>>> acpi_table_begin(&table, table_data);
> >>>>>>
> >>>>>> @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >>>>>> build_append_int_noprefix(table_data, irqflags, 4);
> >>>>>> /* CntReadBase Physical address */
> >>>>>> build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
> >>>>>> +
> >>>>>> /* Platform Timer Count */
> >>>>>> - build_append_int_noprefix(table_data, 0, 4);
> >>>>>> + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
> >>>>>> /* Platform Timer Offset */
> >>>>>> - build_append_int_noprefix(table_data, 0, 4);
> >>>>>> + build_append_int_noprefix(table_data,
> >>>>>> + wdt ? (table_data->len - gtdt_start) +
> >>>>>> + 4 + 4 + 4 /* len of this & following 2 fields to skip */
> >>>>>> + : 0, 4);
> >>>>>> +
> >>>>>> if (vms->ns_el2_virt_timer_irq) {
> >>>>>> /* Virtual EL2 Timer GSIV */
> >>>>>> build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
> >>>>>> @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >>>>>> build_append_int_noprefix(table_data, 0, 4);
> >>>>>> build_append_int_noprefix(table_data, 0, 4);
> >>>>>> }
> >>>>>> +
> >>>>>> + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
> >>>>>> + if (wdt) {
> >>>>>> + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> >>>>>> + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
> >>>>>> + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> >>>>>> + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
> >>>>>> + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
> >>>>>> + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
> >>>>>> + platform_bus_get_irqn(pbus, sd, 0);
> >>>>>> +
> >>>>>> + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
> >>>>>> + build_append_int_noprefix(table_data, 28 /* Length */, 2);
> >>>>>> + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
> >>>>>> + /* RefreshFrame Physical Address */
> >>>>>> + build_append_int_noprefix(table_data, rbase, 8);
> >>>>>> + /* WatchdogControlFrame Physical Address */
> >>>>>> + build_append_int_noprefix(table_data, cbase, 8);
> >>>>>> + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
> >>>>>> + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
> >>>>>> + }
> >>>>>> acpi_table_end(linker, &table);
> >>>>>> }
> >>>>>>
> >>>>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> >>>>>> index cab2e21e8a..a87991b591 100644
> >>>>>> --- a/hw/arm/virt.c
> >>>>>> +++ b/hw/arm/virt.c
> >>>>>> @@ -95,6 +95,7 @@
> >>>>>> #include "hw/cxl/cxl.h"
> >>>>>> #include "hw/cxl/cxl_host.h"
> >>>>>> #include "qemu/guest-random.h"
> >>>>>> +#include "hw/watchdog/sbsa_gwdt.h"
> >>>>>>
> >>>>>> static GlobalProperty arm_virt_compat_defaults[] = {
> >>>>>> { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
> >>>>>> @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
> >>>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> >>>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
> >>>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
> >>>>>> + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
> >>>>>> #ifdef CONFIG_TPM
> >>>>>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> >>>>>> #endif
> >>>>>> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> >>>>>> index 89d0c46445..76aa1bc579 100644
> >>>>>> --- a/hw/core/sysbus-fdt.c
> >>>>>> +++ b/hw/core/sysbus-fdt.c
> >>>>>> @@ -36,6 +36,7 @@
> >>>>>> #include "hw/display/ramfb.h"
> >>>>>> #include "hw/uefi/var-service-api.h"
> >>>>>> #include "hw/arm/fdt.h"
> >>>>>> +#include "hw/watchdog/sbsa_gwdt.h"
> >>>>>>
> >>>>>> /*
> >>>>>> * internal struct that contains the information to create dynamic
> >>>>>> @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
> >>>>>> return 0;
> >>>>>> }
> >>>>>>
> >>>>>> +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
> >>>>>> +{
> >>>>>> + PlatformBusFDTData *data = opaque;
> >>>>>> + PlatformBusDevice *pbus = data->pbus;
> >>>>>> + const char *parent_node = data->pbus_node_name;
> >>>>>> + void *fdt = data->fdt;
> >>>>>> + uint64_t cbase, rbase;
> >>>>>> + char *nodename;
> >>>>>> + int irq;
> >>>>>> +
> >>>>>> + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
> >>>>>> + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
> >>>>>> + irq = platform_bus_get_irqn(pbus, sbdev, 0);
> >>>>>> +
> >>>>>> + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
> >>>>>> + qemu_fdt_add_subnode(fdt, nodename);
> >>>>>> +
> >>>>>> + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
> >>>>>> + qemu_fdt_setprop_cells(fdt, nodename, "reg",
> >>>>>> + cbase, SBSA_GWDT_CMMIO_SIZE,
> >>>>>> + rbase, SBSA_GWDT_RMMIO_SIZE);
> >>>>>> + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
> >>>>>> + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
> >>>>>> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> >>>>>> + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
> >>>>>> +
> >>>>>> + g_free(nodename);
> >>>>>> + return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>> static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
> >>>>>> {
> >>>>>> return 0;
> >>>>>> @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
> >>>>>> TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
> >>>>>> TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
> >>>>>> TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
> >>>>>> + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
> >>>>>> TYPE_BINDING("", NULL), /* last element */
> >>>>>> };
> >>>>>>
> >>>>>> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> >>>>>> index acb970e8b3..c4dd8005b7 100644
> >>>>>> --- a/hw/watchdog/sbsa_gwdt.c
> >>>>>> +++ b/hw/watchdog/sbsa_gwdt.c
> >>>>>> @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
> >>>>>> dc->realize = wdt_sbsa_gwdt_realize;
> >>>>>> device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
> >>>>>> dc->hotpluggable = false;
> >>>>>> + dc->user_creatable = true;
> >>>>>> set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
> >>>>>> dc->vmsd = &vmstate_sbsa_gwdt;
> >>>>>> dc->desc = "SBSA-compliant generic watchdog device";
> >>>>>
> >>>>
> >>>
> >>
> >
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-03-03 9:25 ` [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog Igor Mammedov
2026-05-26 13:58 ` Eric Auger
@ 2026-06-04 16:48 ` Eric Auger
2026-06-04 16:53 ` Eric Auger
2026-06-05 14:45 ` Igor Mammedov
1 sibling, 2 replies; 57+ messages in thread
From: Eric Auger @ 2026-06-04 16:48 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Hi Igor,
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> Allow to use SBSA generic watchdog with virt machine type.
> (includes conditional generation of corresponding FDT and
> ACPI GTDT descriptors)
>
> Use '-device sbsa_gwdt' to command line to enable it.
don't we use '-' instead of '_' in general. At least this is the case
for dynamically instantiable arm-smmuv3 device. Better to align
also this is the terminology used in the fdt compat string
$id: http://devicetree.org/schemas/watchdog/arm,sbsa-gwdt.yaml#
const: arm,sbsa-gwdt
>
> Tested with Fedora 43:
> FDT: -M virt,acpi=off -device sbsa_gwdt
> ACPI: -M virt -device sbsa_gwdt
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> hw/arm/Kconfig | 1 +
> hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
> hw/arm/virt.c | 2 ++
> hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
> hw/watchdog/sbsa_gwdt.c | 1 +
> 5 files changed, 67 insertions(+), 2 deletions(-)
>
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index c66c452737..1222efadd1 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -36,6 +36,7 @@ config ARM_VIRT
> select VIRTIO_MEM_SUPPORTED
> select ACPI_CXL
> select ACPI_HMAT
> + select WDT_SBSA
>
> config CUBIEBOARD
> bool
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 719d2f994e..9c14b1d4d5 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -64,6 +64,7 @@
> #include "hw/virtio/virtio-acpi.h"
> #include "target/arm/cpu.h"
> #include "target/arm/multiprocessing.h"
> +#include "hw/watchdog/sbsa_gwdt.h"
>
> #define ARM_SPI_BASE 32
>
> @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> const uint32_t irqflags = 0; /* Interrupt is Level triggered */
> AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
> .oem_table_id = vms->oem_table_id };
> + uint32_t gtdt_start = table_data->len;
> + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
>
> acpi_table_begin(&table, table_data);
>
> @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> build_append_int_noprefix(table_data, irqflags, 4);
> /* CntReadBase Physical address */
> build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
> +
> /* Platform Timer Count */
> - build_append_int_noprefix(table_data, 0, 4);
> + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
> /* Platform Timer Offset */
> - build_append_int_noprefix(table_data, 0, 4);
> + build_append_int_noprefix(table_data,
> + wdt ? (table_data->len - gtdt_start) +
> + 4 + 4 + 4 /* len of this & following 2 fields to skip */
> + : 0, 4);
> +
> if (vms->ns_el2_virt_timer_irq) {
> /* Virtual EL2 Timer GSIV */
> build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
> @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> build_append_int_noprefix(table_data, 0, 4);
> build_append_int_noprefix(table_data, 0, 4);
> }
> +
> + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
5.124
> + if (wdt) {
> + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
> + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
> + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
> + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
> + platform_bus_get_irqn(pbus, sd, 0);
> +
> + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
> + build_append_int_noprefix(table_data, 28 /* Length */, 2);
> + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
> + /* RefreshFrame Physical Address */
> + build_append_int_noprefix(table_data, rbase, 8);
> + /* WatchdogControlFrame Physical Address */
> + build_append_int_noprefix(table_data, cbase, 8);
> + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
> + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
level, active high, non secure
> + }
> acpi_table_end(linker, &table);
> }
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index cab2e21e8a..a87991b591 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -95,6 +95,7 @@
> #include "hw/cxl/cxl.h"
> #include "hw/cxl/cxl_host.h"
> #include "qemu/guest-random.h"
> +#include "hw/watchdog/sbsa_gwdt.h"
>
> static GlobalProperty arm_virt_compat_defaults[] = {
> { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
> @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
> + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
> #ifdef CONFIG_TPM
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> #endif
> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> index 89d0c46445..76aa1bc579 100644
> --- a/hw/core/sysbus-fdt.c
> +++ b/hw/core/sysbus-fdt.c
> @@ -36,6 +36,7 @@
> #include "hw/display/ramfb.h"
> #include "hw/uefi/var-service-api.h"
> #include "hw/arm/fdt.h"
> +#include "hw/watchdog/sbsa_gwdt.h"
>
> /*
> * internal struct that contains the information to create dynamic
> @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
> return 0;
> }
>
> +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
> +{
> + PlatformBusFDTData *data = opaque;
> + PlatformBusDevice *pbus = data->pbus;
> + const char *parent_node = data->pbus_node_name;
> + void *fdt = data->fdt;
> + uint64_t cbase, rbase;
> + char *nodename;
> + int irq;
> +
> + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
> + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
> + irq = platform_bus_get_irqn(pbus, sbdev, 0);
> +
> + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
> + qemu_fdt_add_subnode(fdt, nodename);
> +
> + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
> + qemu_fdt_setprop_cells(fdt, nodename, "reg",
> + cbase, SBSA_GWDT_CMMIO_SIZE,
> + rbase, SBSA_GWDT_RMMIO_SIZE);
> + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
> + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
> +
> + g_free(nodename);
> + return 0;
> +}
> +
> static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
> {
> return 0;
> @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
> TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
> TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
> TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
> + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
> TYPE_BINDING("", NULL), /* last element */
> };
>
> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> index acb970e8b3..c4dd8005b7 100644
> --- a/hw/watchdog/sbsa_gwdt.c
> +++ b/hw/watchdog/sbsa_gwdt.c
> @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
> dc->realize = wdt_sbsa_gwdt_realize;
> device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
> dc->hotpluggable = false;
> + dc->user_creatable = true;
> set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
> dc->vmsd = &vmstate_sbsa_gwdt;
> dc->desc = "SBSA-compliant generic watchdog device";
Thanks
Eric
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-06-04 16:48 ` Eric Auger
@ 2026-06-04 16:53 ` Eric Auger
2026-06-05 14:45 ` Igor Mammedov
1 sibling, 0 replies; 57+ messages in thread
From: Eric Auger @ 2026-06-04 16:53 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On 6/4/26 6:48 PM, Eric Auger wrote:
> Hi Igor,
>
> On 3/3/26 10:25 AM, Igor Mammedov wrote:
>> Allow to use SBSA generic watchdog with virt machine type.
>> (includes conditional generation of corresponding FDT and
>> ACPI GTDT descriptors)
>>
>> Use '-device sbsa_gwdt' to command line to enable it.
> don't we use '-' instead of '_' in general. At least this is the case
> for dynamically instantiable arm-smmuv3 device. Better to align
>
> also this is the terminology used in the fdt compat string
> $id: http://devicetree.org/schemas/watchdog/arm,sbsa-gwdt.yaml#
> const: arm,sbsa-gwdt
I realize this is not your choice as the device is already named that
way. #define TYPE_WDT_SBSA "sbsa_gwdt"
So I don't think we can anything about that anymore
although in general other devices use "-" I think
#define TYPE_UEFI_VARS_SYSBUS "uefi-vars-sysbus"
Eric
>
>>
>> Tested with Fedora 43:
>> FDT: -M virt,acpi=off -device sbsa_gwdt
>> ACPI: -M virt -device sbsa_gwdt
>>
>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>> ---
>> hw/arm/Kconfig | 1 +
>> hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
>> hw/arm/virt.c | 2 ++
>> hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
>> hw/watchdog/sbsa_gwdt.c | 1 +
>> 5 files changed, 67 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>> index c66c452737..1222efadd1 100644
>> --- a/hw/arm/Kconfig
>> +++ b/hw/arm/Kconfig
>> @@ -36,6 +36,7 @@ config ARM_VIRT
>> select VIRTIO_MEM_SUPPORTED
>> select ACPI_CXL
>> select ACPI_HMAT
>> + select WDT_SBSA
>>
>> config CUBIEBOARD
>> bool
>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>> index 719d2f994e..9c14b1d4d5 100644
>> --- a/hw/arm/virt-acpi-build.c
>> +++ b/hw/arm/virt-acpi-build.c
>> @@ -64,6 +64,7 @@
>> #include "hw/virtio/virtio-acpi.h"
>> #include "target/arm/cpu.h"
>> #include "target/arm/multiprocessing.h"
>> +#include "hw/watchdog/sbsa_gwdt.h"
>>
>> #define ARM_SPI_BASE 32
>>
>> @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>> const uint32_t irqflags = 0; /* Interrupt is Level triggered */
>> AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
>> .oem_table_id = vms->oem_table_id };
>> + uint32_t gtdt_start = table_data->len;
>> + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
>>
>> acpi_table_begin(&table, table_data);
>>
>> @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>> build_append_int_noprefix(table_data, irqflags, 4);
>> /* CntReadBase Physical address */
>> build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
>> +
>> /* Platform Timer Count */
>> - build_append_int_noprefix(table_data, 0, 4);
>> + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
>> /* Platform Timer Offset */
>> - build_append_int_noprefix(table_data, 0, 4);
>> + build_append_int_noprefix(table_data,
>> + wdt ? (table_data->len - gtdt_start) +
>> + 4 + 4 + 4 /* len of this & following 2 fields to skip */
>> + : 0, 4);
>> +
>> if (vms->ns_el2_virt_timer_irq) {
>> /* Virtual EL2 Timer GSIV */
>> build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
>> @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>> build_append_int_noprefix(table_data, 0, 4);
>> build_append_int_noprefix(table_data, 0, 4);
>> }
>> +
>> + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
> 5.124
>> + if (wdt) {
>> + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
>> + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
>> + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
>> + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
>> + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
>> + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
>> + platform_bus_get_irqn(pbus, sd, 0);
>> +
>> + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
>> + build_append_int_noprefix(table_data, 28 /* Length */, 2);
>> + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
>> + /* RefreshFrame Physical Address */
>> + build_append_int_noprefix(table_data, rbase, 8);
>> + /* WatchdogControlFrame Physical Address */
>> + build_append_int_noprefix(table_data, cbase, 8);
>> + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
>> + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
> level, active high, non secure
>> + }
>> acpi_table_end(linker, &table);
>> }
>>
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index cab2e21e8a..a87991b591 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -95,6 +95,7 @@
>> #include "hw/cxl/cxl.h"
>> #include "hw/cxl/cxl_host.h"
>> #include "qemu/guest-random.h"
>> +#include "hw/watchdog/sbsa_gwdt.h"
>>
>> static GlobalProperty arm_virt_compat_defaults[] = {
>> { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
>> @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
>> + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
>> #ifdef CONFIG_TPM
>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
>> #endif
>> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
>> index 89d0c46445..76aa1bc579 100644
>> --- a/hw/core/sysbus-fdt.c
>> +++ b/hw/core/sysbus-fdt.c
>> @@ -36,6 +36,7 @@
>> #include "hw/display/ramfb.h"
>> #include "hw/uefi/var-service-api.h"
>> #include "hw/arm/fdt.h"
>> +#include "hw/watchdog/sbsa_gwdt.h"
>>
>> /*
>> * internal struct that contains the information to create dynamic
>> @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
>> return 0;
>> }
>>
>> +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
>> +{
>> + PlatformBusFDTData *data = opaque;
>> + PlatformBusDevice *pbus = data->pbus;
>> + const char *parent_node = data->pbus_node_name;
>> + void *fdt = data->fdt;
>> + uint64_t cbase, rbase;
>> + char *nodename;
>> + int irq;
>> +
>> + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
>> + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
>> + irq = platform_bus_get_irqn(pbus, sbdev, 0);
>> +
>> + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
>> + qemu_fdt_add_subnode(fdt, nodename);
>> +
>> + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
>> + qemu_fdt_setprop_cells(fdt, nodename, "reg",
>> + cbase, SBSA_GWDT_CMMIO_SIZE,
>> + rbase, SBSA_GWDT_RMMIO_SIZE);
>> + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
>> + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
>> + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
>> + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
>> +
>> + g_free(nodename);
>> + return 0;
>> +}
>> +
>> static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
>> {
>> return 0;
>> @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
>> TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
>> TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
>> TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
>> + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
>> TYPE_BINDING("", NULL), /* last element */
>> };
>>
>> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
>> index acb970e8b3..c4dd8005b7 100644
>> --- a/hw/watchdog/sbsa_gwdt.c
>> +++ b/hw/watchdog/sbsa_gwdt.c
>> @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
>> dc->realize = wdt_sbsa_gwdt_realize;
>> device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
>> dc->hotpluggable = false;
>> + dc->user_creatable = true;
>> set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
>> dc->vmsd = &vmstate_sbsa_gwdt;
>> dc->desc = "SBSA-compliant generic watchdog device";
> Thanks
>
> Eric
>
>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog
2026-06-04 16:48 ` Eric Auger
2026-06-04 16:53 ` Eric Auger
@ 2026-06-05 14:45 ` Igor Mammedov
1 sibling, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-06-05 14:45 UTC (permalink / raw)
To: Eric Auger
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm
On Thu, 4 Jun 2026 18:48:28 +0200
Eric Auger <eauger@redhat.com> wrote:
> Hi Igor,
>
> On 3/3/26 10:25 AM, Igor Mammedov wrote:
> > Allow to use SBSA generic watchdog with virt machine type.
> > (includes conditional generation of corresponding FDT and
> > ACPI GTDT descriptors)
> >
> > Use '-device sbsa_gwdt' to command line to enable it.
> don't we use '-' instead of '_' in general. At least this is the case
> for dynamically instantiable arm-smmuv3 device. Better to align
device names are usually ABI, when the get leaked to users,
and another place it might break would be migration.
I agree with s/_/-/, but let me check/test. if it doesn't break
migration, I think we are good to go with rename.
>
> also this is the terminology used in the fdt compat string
> $id: http://devicetree.org/schemas/watchdog/arm,sbsa-gwdt.yaml#
> const: arm,sbsa-gwdt
>
> >
> > Tested with Fedora 43:
> > FDT: -M virt,acpi=off -device sbsa_gwdt
> > ACPI: -M virt -device sbsa_gwdt
> >
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > hw/arm/Kconfig | 1 +
> > hw/arm/virt-acpi-build.c | 33 +++++++++++++++++++++++++++++++--
> > hw/arm/virt.c | 2 ++
> > hw/core/sysbus-fdt.c | 32 ++++++++++++++++++++++++++++++++
> > hw/watchdog/sbsa_gwdt.c | 1 +
> > 5 files changed, 67 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index c66c452737..1222efadd1 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -36,6 +36,7 @@ config ARM_VIRT
> > select VIRTIO_MEM_SUPPORTED
> > select ACPI_CXL
> > select ACPI_HMAT
> > + select WDT_SBSA
> >
> > config CUBIEBOARD
> > bool
> > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> > index 719d2f994e..9c14b1d4d5 100644
> > --- a/hw/arm/virt-acpi-build.c
> > +++ b/hw/arm/virt-acpi-build.c
> > @@ -64,6 +64,7 @@
> > #include "hw/virtio/virtio-acpi.h"
> > #include "target/arm/cpu.h"
> > #include "target/arm/multiprocessing.h"
> > +#include "hw/watchdog/sbsa_gwdt.h"
> >
> > #define ARM_SPI_BASE 32
> >
> > @@ -863,6 +864,8 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> > const uint32_t irqflags = 0; /* Interrupt is Level triggered */
> > AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
> > .oem_table_id = vms->oem_table_id };
> > + uint32_t gtdt_start = table_data->len;
> > + Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
> >
> > acpi_table_begin(&table, table_data);
> >
> > @@ -893,10 +896,15 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> > build_append_int_noprefix(table_data, irqflags, 4);
> > /* CntReadBase Physical address */
> > build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
> > +
> > /* Platform Timer Count */
> > - build_append_int_noprefix(table_data, 0, 4);
> > + build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
> > /* Platform Timer Offset */
> > - build_append_int_noprefix(table_data, 0, 4);
> > + build_append_int_noprefix(table_data,
> > + wdt ? (table_data->len - gtdt_start) +
> > + 4 + 4 + 4 /* len of this & following 2 fields to skip */
> > + : 0, 4);
> > +
> > if (vms->ns_el2_virt_timer_irq) {
> > /* Virtual EL2 Timer GSIV */
> > build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_VIRT_IRQ, 4);
> > @@ -906,6 +914,27 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> > build_append_int_noprefix(table_data, 0, 4);
> > build_append_int_noprefix(table_data, 0, 4);
> > }
> > +
> > + /* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
> 5.124
> > + if (wdt) {
> > + PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> > + SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
> > + hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> > + hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
> > + hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
> > + int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
> > + platform_bus_get_irqn(pbus, sd, 0);
> > +
> > + build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
> > + build_append_int_noprefix(table_data, 28 /* Length */, 2);
> > + build_append_int_noprefix(table_data, 0, 1); /* Reserved */
> > + /* RefreshFrame Physical Address */
> > + build_append_int_noprefix(table_data, rbase, 8);
> > + /* WatchdogControlFrame Physical Address */
> > + build_append_int_noprefix(table_data, cbase, 8);
> > + build_append_int_noprefix(table_data, irq, 4); /* Watchdog Timer GSIV */
> > + build_append_int_noprefix(table_data, 0, 4); /* Watchdog Timer Flags */
> level, active high, non secure
> > + }
> > acpi_table_end(linker, &table);
> > }
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index cab2e21e8a..a87991b591 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -95,6 +95,7 @@
> > #include "hw/cxl/cxl.h"
> > #include "hw/cxl/cxl_host.h"
> > #include "qemu/guest-random.h"
> > +#include "hw/watchdog/sbsa_gwdt.h"
> >
> > static GlobalProperty arm_virt_compat_defaults[] = {
> > { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
> > @@ -3474,6 +3475,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
> > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
> > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_ARM_SMMUV3);
> > + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_WDT_SBSA);
> > #ifdef CONFIG_TPM
> > machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> > #endif
> > diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> > index 89d0c46445..76aa1bc579 100644
> > --- a/hw/core/sysbus-fdt.c
> > +++ b/hw/core/sysbus-fdt.c
> > @@ -36,6 +36,7 @@
> > #include "hw/display/ramfb.h"
> > #include "hw/uefi/var-service-api.h"
> > #include "hw/arm/fdt.h"
> > +#include "hw/watchdog/sbsa_gwdt.h"
> >
> > /*
> > * internal struct that contains the information to create dynamic
> > @@ -118,6 +119,36 @@ static int add_uefi_vars_node(SysBusDevice *sbdev, void *opaque)
> > return 0;
> > }
> >
> > +static int add_sbsa_gwdt_node(SysBusDevice *sbdev, void *opaque)
> > +{
> > + PlatformBusFDTData *data = opaque;
> > + PlatformBusDevice *pbus = data->pbus;
> > + const char *parent_node = data->pbus_node_name;
> > + void *fdt = data->fdt;
> > + uint64_t cbase, rbase;
> > + char *nodename;
> > + int irq;
> > +
> > + cbase = platform_bus_get_mmio_addr(pbus, sbdev, 1); /* control frame */
> > + rbase = platform_bus_get_mmio_addr(pbus, sbdev, 0); /* refresh frame */
> > + irq = platform_bus_get_irqn(pbus, sbdev, 0);
> > +
> > + nodename = g_strdup_printf("%s/watchdog@%" PRIx64, parent_node, cbase);
> > + qemu_fdt_add_subnode(fdt, nodename);
> > +
> > + qemu_fdt_setprop_string(fdt, nodename, "compatible", "arm,sbsa-gwdt");
> > + qemu_fdt_setprop_cells(fdt, nodename, "reg",
> > + cbase, SBSA_GWDT_CMMIO_SIZE,
> > + rbase, SBSA_GWDT_RMMIO_SIZE);
> > + qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
> > + GIC_FDT_IRQ_TYPE_SPI, data->irq_start + irq,
> > + GIC_FDT_IRQ_FLAGS_LEVEL_HI);
> > + qemu_fdt_setprop_cell(fdt, nodename, "timeout-sec", 30);
> > +
> > + g_free(nodename);
> > + return 0;
> > +}
> > +
> > static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
> > {
> > return 0;
> > @@ -140,6 +171,7 @@ static const BindingEntry bindings[] = {
> > TYPE_BINDING(TYPE_ARM_SMMUV3, no_fdt_node),
> > TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
> > TYPE_BINDING(TYPE_UEFI_VARS_SYSBUS, add_uefi_vars_node),
> > + TYPE_BINDING(TYPE_WDT_SBSA, add_sbsa_gwdt_node),
> > TYPE_BINDING("", NULL), /* last element */
> > };
> >
> > diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> > index acb970e8b3..c4dd8005b7 100644
> > --- a/hw/watchdog/sbsa_gwdt.c
> > +++ b/hw/watchdog/sbsa_gwdt.c
> > @@ -285,6 +285,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
> > dc->realize = wdt_sbsa_gwdt_realize;
> > device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
> > dc->hotpluggable = false;
> > + dc->user_creatable = true;
> > set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
> > dc->vmsd = &vmstate_sbsa_gwdt;
> > dc->desc = "SBSA-compliant generic watchdog device";
> Thanks
>
> Eric
>
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 10/21] arm: sbsa_gwdt: add 'wdat' option
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (8 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 09/21] arm: virt: create sbsa_gwdt watchdog Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-26 14:24 ` Eric Auger
2026-03-03 9:25 ` [PATCH v2 11/21] arm: virt: add support for WDAT based watchdog Igor Mammedov
` (12 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
it will be used by arm/virt board, to pick WDAT compatible watchdog impl.
and act as switch over to WDAT ACPI table vesus default GTDT ACPI table.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
include/hw/watchdog/sbsa_gwdt.h | 1 +
hw/watchdog/sbsa_gwdt.c | 8 ++++++++
2 files changed, 9 insertions(+)
diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h
index 307a4f291a..dc77e6be60 100644
--- a/include/hw/watchdog/sbsa_gwdt.h
+++ b/include/hw/watchdog/sbsa_gwdt.h
@@ -73,6 +73,7 @@ typedef struct SBSA_GWDTState {
uint32_t woru;
uint32_t wcvl;
uint32_t wcvu;
+ bool wdat;
} SBSA_GWDTState;
#endif /* WDT_SBSA_GWDT_H */
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index c4dd8005b7..40d80f7f2b 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -265,6 +265,13 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
sysbus_init_irq(sbd, &s->irq);
+ /*
+ * WDAT supports only upto 1KHz resolution,
+ */
+ if (s->wdat) {
+ s->freq = 1000;
+ }
+
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sbsa_gwdt_timer_sysinterrupt,
dev);
}
@@ -276,6 +283,7 @@ static const Property wdt_sbsa_gwdt_props[] = {
*/
DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
1000000000),
+ DEFINE_PROP_BOOL("wdat", struct SBSA_GWDTState, wdat, false),
};
static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 10/21] arm: sbsa_gwdt: add 'wdat' option
2026-03-03 9:25 ` [PATCH v2 10/21] arm: sbsa_gwdt: add 'wdat' option Igor Mammedov
@ 2026-05-26 14:24 ` Eric Auger
2026-05-27 12:55 ` Igor Mammedov
0 siblings, 1 reply; 57+ messages in thread
From: Eric Auger @ 2026-05-26 14:24 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> it will be used by arm/virt board, to pick WDAT compatible watchdog impl.
> and act as switch over to WDAT ACPI table vesus default GTDT ACPI table.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> include/hw/watchdog/sbsa_gwdt.h | 1 +
> hw/watchdog/sbsa_gwdt.c | 8 ++++++++
> 2 files changed, 9 insertions(+)
>
> diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h
> index 307a4f291a..dc77e6be60 100644
> --- a/include/hw/watchdog/sbsa_gwdt.h
> +++ b/include/hw/watchdog/sbsa_gwdt.h
> @@ -73,6 +73,7 @@ typedef struct SBSA_GWDTState {
> uint32_t woru;
> uint32_t wcvl;
> uint32_t wcvu;
> + bool wdat;
> } SBSA_GWDTState;
>
> #endif /* WDT_SBSA_GWDT_H */
> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> index c4dd8005b7..40d80f7f2b 100644
> --- a/hw/watchdog/sbsa_gwdt.c
> +++ b/hw/watchdog/sbsa_gwdt.c
> @@ -265,6 +265,13 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
>
> sysbus_init_irq(sbd, &s->irq);
>
> + /*
> + * WDAT supports only upto 1KHz resolution,
> + */
> + if (s->wdat) {
> + s->freq = 1000;
where is it specified in the spec?
Thanks
Eric
> + }
> +
> s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sbsa_gwdt_timer_sysinterrupt,
> dev);
> }
> @@ -276,6 +283,7 @@ static const Property wdt_sbsa_gwdt_props[] = {
> */
> DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
> 1000000000),
> + DEFINE_PROP_BOOL("wdat", struct SBSA_GWDTState, wdat, false),
> };
>
> static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 10/21] arm: sbsa_gwdt: add 'wdat' option
2026-05-26 14:24 ` Eric Auger
@ 2026-05-27 12:55 ` Igor Mammedov
0 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-05-27 12:55 UTC (permalink / raw)
To: Eric Auger
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm
On Tue, 26 May 2026 16:24:59 +0200
Eric Auger <eauger@redhat.com> wrote:
> On 3/3/26 10:25 AM, Igor Mammedov wrote:
> > it will be used by arm/virt board, to pick WDAT compatible watchdog impl.
> > and act as switch over to WDAT ACPI table vesus default GTDT ACPI table.
> >
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > include/hw/watchdog/sbsa_gwdt.h | 1 +
> > hw/watchdog/sbsa_gwdt.c | 8 ++++++++
> > 2 files changed, 9 insertions(+)
> >
> > diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h
> > index 307a4f291a..dc77e6be60 100644
> > --- a/include/hw/watchdog/sbsa_gwdt.h
> > +++ b/include/hw/watchdog/sbsa_gwdt.h
> > @@ -73,6 +73,7 @@ typedef struct SBSA_GWDTState {
> > uint32_t woru;
> > uint32_t wcvl;
> > uint32_t wcvu;
> > + bool wdat;
> > } SBSA_GWDTState;
> >
> > #endif /* WDT_SBSA_GWDT_H */
> > diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> > index c4dd8005b7..40d80f7f2b 100644
> > --- a/hw/watchdog/sbsa_gwdt.c
> > +++ b/hw/watchdog/sbsa_gwdt.c
> > @@ -265,6 +265,13 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
> >
> > sysbus_init_irq(sbd, &s->irq);
> >
> > + /*
> > + * WDAT supports only upto 1KHz resolution,
> > + */
> > + if (s->wdat) {
> > + s->freq = 1000;
> where is it specified in the spec?
next patch has link to WDAT spec and
comment around relevant field:
+ /*
+ * WDAT spec suports only 1KHz or more coarse watchdog timer,
+ * Set resolution to minimum supported 1ms.
+ * Before starting watchdog Windows set countdown value to 5min.
+ */
+ g_assert(freq <= 1000);
+ build_append_int_noprefix(table_data, 1, 4);/* Timer Period, ms */
it's the hack to make gwdt usable for wdat and is applied only when
wdat is enabled, if not the gwdt is instantiated with native 1G and
provides corresponding fdt.
>
> Thanks
>
> Eric
>
> > + }
> > +
> > s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sbsa_gwdt_timer_sysinterrupt,
> > dev);
> > }
> > @@ -276,6 +283,7 @@ static const Property wdt_sbsa_gwdt_props[] = {
> > */
> > DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
> > 1000000000),
> > + DEFINE_PROP_BOOL("wdat", struct SBSA_GWDTState, wdat, false),
> > };
> >
> > static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 11/21] arm: virt: add support for WDAT based watchdog
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (9 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 10/21] arm: sbsa_gwdt: add 'wdat' option Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 12/21] tests: acpi: arm/virt: whitelist new WDAT table Igor Mammedov
` (11 subsequent siblings)
22 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
And generate WDAT table tailored for sbsa_gwdt and disable
watchdog entry in GTDT ACPI table if WDAT is enabled,
since they are mutualy exclusive due to different
timer resolution of sbsa_gwdt.
To enable use "-device sbsa-gwdt,wdat=on" option
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
include/hw/acpi/wdat-gwdt.h | 19 ++++++++
hw/acpi/meson.build | 2 +
hw/acpi/wdat-gwdt-stub.c | 16 +++++++
hw/acpi/wdat-gwdt.c | 92 +++++++++++++++++++++++++++++++++++++
hw/arm/virt-acpi-build.c | 58 +++++++++++++++++------
5 files changed, 172 insertions(+), 15 deletions(-)
create mode 100644 include/hw/acpi/wdat-gwdt.h
create mode 100644 hw/acpi/wdat-gwdt-stub.c
create mode 100644 hw/acpi/wdat-gwdt.c
diff --git a/include/hw/acpi/wdat-gwdt.h b/include/hw/acpi/wdat-gwdt.h
new file mode 100644
index 0000000000..42339e031e
--- /dev/null
+++ b/include/hw/acpi/wdat-gwdt.h
@@ -0,0 +1,19 @@
+/*
+ * GWDT Watchdog Action Table (WDAT) definition
+ *
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef QEMU_HW_ACPI_WDAT_GWDT_H
+#define QEMU_HW_ACPI_WDAT_GWDT_H
+
+#include "hw/acpi/aml-build.h"
+#include "hw/watchdog/sbsa_gwdt.h"
+
+void build_gwdt_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+ const char *oem_table_id, uint64_t rbase, uint64_t cbase,
+ uint64_t freq);
+
+#endif /* QEMU_HW_ACPI_WDAT_GWDT_H */
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
index 22290ca835..189bbb0257 100644
--- a/hw/acpi/meson.build
+++ b/hw/acpi/meson.build
@@ -28,12 +28,14 @@ acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c', 'ic
acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c'))
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
+acpi_ss.add(when: 'CONFIG_WDT_SBSA', if_true: files('wdat-gwdt.c'))
if have_tpm
acpi_ss.add(files('tpm.c'))
endif
system_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c'))
system_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_false: files('pci-bridge-stub.c'))
system_ss.add(when: 'CONFIG_ACPI_ICH9', if_false: files('wdat-ich9-stub.c'))
+system_ss.add(when: 'CONFIG_WDT_SBSA', if_false: files('wdat-gwdt-stub.c'))
system_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
system_ss.add(when: 'CONFIG_GHES_CPER', if_true: files('ghes_cper.c'))
system_ss.add(when: 'CONFIG_GHES_CPER', if_false: files('ghes_cper_stub.c'))
diff --git a/hw/acpi/wdat-gwdt-stub.c b/hw/acpi/wdat-gwdt-stub.c
new file mode 100644
index 0000000000..4d43783f70
--- /dev/null
+++ b/hw/acpi/wdat-gwdt-stub.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/wdat-gwdt.h"
+
+void build_gwdt_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+ const char *oem_table_id, uint64_t rbase, uint64_t cbase,
+ uint64_t freq)
+{
+ g_assert_not_reached();
+}
diff --git a/hw/acpi/wdat-gwdt.c b/hw/acpi/wdat-gwdt.c
new file mode 100644
index 0000000000..226ba3f01e
--- /dev/null
+++ b/hw/acpi/wdat-gwdt.c
@@ -0,0 +1,92 @@
+/*
+ * SBSA GWDT Watchdog Action Table (WDAT)
+ *
+ * Copyright Red Hat, Inc. 2026
+ * Author(s): Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/wdat-gwdt.h"
+#include "hw/acpi/wdat.h"
+#include "hw/watchdog/sbsa_gwdt.h"
+
+#define GWDT_REG(base, reg_offset, reg_width) { \
+ .space_id = AML_AS_SYSTEM_MEMORY, \
+ .address = base + reg_offset, .bit_width = reg_width, \
+ .access_width = AML_DWORD_ACC };
+
+/*
+ * "Hardware Watchdog Timers Design Specification"
+ * https://uefi.org/acpi 'Watchdog Action Table (WDAT)'
+ */
+void build_gwdt_wdat(GArray *table_data, BIOSLinker *linker, const char *oem_id,
+ const char *oem_table_id, uint64_t rbase, uint64_t cbase,
+ uint64_t freq)
+{
+ AcpiTable table = { .sig = "WDAT", .rev = 1, .oem_id = oem_id,
+ .oem_table_id = oem_table_id };
+
+ struct AcpiGenericAddress wrr = GWDT_REG(rbase, 0x0, 32);
+ struct AcpiGenericAddress wor_l = GWDT_REG(cbase, SBSA_GWDT_WOR, 32);
+ struct AcpiGenericAddress wcs = GWDT_REG(cbase, SBSA_GWDT_WCS, 32);
+
+ acpi_table_begin(&table, table_data);
+ build_append_int_noprefix(table_data, 0x20, 4); /* Watchdog Header Length */
+ build_append_int_noprefix(table_data, 0xff, 2); /* PCI Segment */
+ build_append_int_noprefix(table_data, 0xff, 1); /* PCI Bus Number */
+ build_append_int_noprefix(table_data, 0xff, 1); /* PCI Device Number */
+ build_append_int_noprefix(table_data, 0xff, 1); /* PCI Function Number */
+ build_append_int_noprefix(table_data, 0, 3); /* Reserved */
+ /*
+ * WDAT spec suports only 1KHz or more coarse watchdog timer,
+ * Set resolution to minimum supported 1ms.
+ * Before starting watchdog Windows set countdown value to 5min.
+ */
+ g_assert(freq <= 1000);
+ build_append_int_noprefix(table_data, 1, 4);/* Timer Period, ms */
+ /*
+ * Needs to be more than 4min, otherwise Windows 11 won't start watchdog.
+ * Set max to limits to arbitrary max 10min and min to 5sec.
+ */
+ build_append_int_noprefix(table_data, 600 * freq, 4);/* Maximum Count */
+ build_append_int_noprefix(table_data, 5 * freq, 4); /* Minimum Count */
+ /*
+ * WATCHDOG_ENABLED
+ */
+ build_append_int_noprefix(table_data, 0x81, 1); /* Watchdog Flags */
+ build_append_int_noprefix(table_data, 0, 3); /* Reserved */
+ /*
+ * watchdog instruction entries
+ */
+ build_append_int_noprefix(table_data, 8, 4);
+ /* Action table */
+ build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_RUNNING_STATE,
+ WDAT_INS_READ_VALUE,
+ wcs, 0x1, 0x1);
+ build_append_wdat_ins(table_data, WDAT_ACTION_RESET,
+ WDAT_INS_WRITE_VALUE,
+ wrr, 0x1, 0x7);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_COUNTDOWN_PERIOD,
+ WDAT_INS_WRITE_COUNTDOWN,
+ wor_l, 0, 0xffffffff);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_RUNNING_STATE,
+ WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+ wcs, 1, 0x00000001);
+ build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_STOPPED_STATE,
+ WDAT_INS_READ_VALUE,
+ wcs, 0x0, 0x00000001);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_STOPPED_STATE,
+ WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+ wcs, 0x0, 0x00000001);
+ build_append_wdat_ins(table_data, WDAT_ACTION_QUERY_WATCHDOG_STATUS,
+ WDAT_INS_READ_VALUE,
+ wcs, 0x4, 0x00000004);
+ build_append_wdat_ins(table_data, WDAT_ACTION_SET_WATCHDOG_STATUS,
+ WDAT_INS_WRITE_VALUE | WDAT_INS_PRESERVE_REGISTER,
+ wrr, 0x4, 0x4);
+
+ acpi_table_end(linker, &table);
+}
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 9c14b1d4d5..e9670b1a2b 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -65,6 +65,7 @@
#include "target/arm/cpu.h"
#include "target/arm/multiprocessing.h"
#include "hw/watchdog/sbsa_gwdt.h"
+#include "hw/acpi/wdat-gwdt.h"
#define ARM_SPI_BASE 32
@@ -849,12 +850,25 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
acpi_table_end(linker, &table);
}
+static void virt_get_wdt_options(VirtMachineState *vms, Object *wdt,
+ hwaddr *rbase, hwaddr *cbase, int *irq)
+{
+ PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
+ SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
+ hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
+ *rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
+ *cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
+ *irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
+ platform_bus_get_irqn(pbus, sd, 0);
+}
+
/*
* ACPI spec, Revision 6.5
* 5.2.25 Generic Timer Description Table (GTDT)
*/
static void
-build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
+build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms,
+ Object *wdt, bool add_watchdog)
{
/*
* Table 5-117 Flag Definitions
@@ -865,7 +879,6 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
AcpiTable table = { .sig = "GTDT", .rev = 3, .oem_id = vms->oem_id,
.oem_table_id = vms->oem_table_id };
uint32_t gtdt_start = table_data->len;
- Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
acpi_table_begin(&table, table_data);
@@ -898,12 +911,12 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8);
/* Platform Timer Count */
- build_append_int_noprefix(table_data, wdt ? 1 : 0, 4);
+ build_append_int_noprefix(table_data, add_watchdog ? 1 : 0, 4);
/* Platform Timer Offset */
build_append_int_noprefix(table_data,
- wdt ? (table_data->len - gtdt_start) +
- 4 + 4 + 4 /* len of this & following 2 fields to skip */
- : 0, 4);
+ add_watchdog ? (table_data->len - gtdt_start) +
+ 4 + 4 + 4 /* len of this & following 2 fields to skip */
+ : 0, 4);
if (vms->ns_el2_virt_timer_irq) {
/* Virtual EL2 Timer GSIV */
@@ -916,14 +929,10 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
}
/* ACPI 6.5 spec: 5.2.25.2 ARM Generic Watchdog Structure (Table 5-124) */
- if (wdt) {
- PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
- SysBusDevice *sd = SYS_BUS_DEVICE(wdt);
- hwaddr mmio_base = vms->memmap[VIRT_PLATFORM_BUS].base;
- hwaddr rbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 0);
- hwaddr cbase = mmio_base + platform_bus_get_mmio_addr(pbus, sd, 1);
- int irq = ARM_SPI_BASE + vms->irqmap[VIRT_PLATFORM_BUS] +
- platform_bus_get_irqn(pbus, sd, 0);
+ if (add_watchdog) {
+ int irq;
+ hwaddr rbase, cbase;
+ virt_get_wdt_options(vms, wdt, &rbase, &cbase, &irq);
build_append_int_noprefix(table_data, 1 /* Type: Watchdog GT */, 1);
build_append_int_noprefix(table_data, 28 /* Length */, 2);
@@ -1282,8 +1291,14 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
GArray *table_offsets;
unsigned dsdt, xsdt;
+ bool has_wdat = false;
GArray *tables_blob = tables->table_data;
MachineState *ms = MACHINE(vms);
+ Object *wdt = object_resolve_type_unambiguous(TYPE_WDT_SBSA, NULL);
+
+ if (wdt) {
+ has_wdat = object_property_get_bool(wdt, "wdat", &error_abort);
+ }
table_offsets = g_array_new(false, true /* clear */,
sizeof(uint32_t));
@@ -1303,6 +1318,19 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables_blob);
build_madt(tables_blob, tables->linker, vms);
+ acpi_add_table(table_offsets, tables_blob);
+ if (wdt && has_wdat) {
+ int irq;
+ hwaddr rbase, cbase;
+ uint64_t freq = object_property_get_uint(wdt, "clock-frequency",
+ &error_abort);
+ virt_get_wdt_options(vms, wdt, &rbase, &cbase, &irq);
+
+ build_gwdt_wdat(tables_blob, tables->linker,
+ vms->oem_id, vms->oem_table_id,
+ rbase, cbase, freq);
+ }
+
if (!vmc->no_cpu_topology) {
acpi_add_table(table_offsets, tables_blob);
build_pptt(tables_blob, tables->linker, ms,
@@ -1310,7 +1338,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
}
acpi_add_table(table_offsets, tables_blob);
- build_gtdt(tables_blob, tables->linker, vms);
+ build_gtdt(tables_blob, tables->linker, vms, wdt, wdt && !has_wdat);
acpi_add_table(table_offsets, tables_blob);
{
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH v2 12/21] tests: acpi: arm/virt: whitelist new WDAT table
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (10 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 11/21] arm: virt: add support for WDAT based watchdog Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-26 14:42 ` Eric Auger
2026-03-03 9:25 ` [PATCH v2 13/21] tests: acpi: arm/virt: add WDAT table test case Igor Mammedov
` (10 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 +
tests/data/acpi/aarch64/virt/WDAT.wdat | 0
2 files changed, 1 insertion(+)
create mode 100644 tests/data/acpi/aarch64/virt/WDAT.wdat
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..135186b40b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,2 @@
/* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/aarch64/virt/WDAT.wdat",
diff --git a/tests/data/acpi/aarch64/virt/WDAT.wdat b/tests/data/acpi/aarch64/virt/WDAT.wdat
new file mode 100644
index 0000000000..e69de29bb2
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 12/21] tests: acpi: arm/virt: whitelist new WDAT table
2026-03-03 9:25 ` [PATCH v2 12/21] tests: acpi: arm/virt: whitelist new WDAT table Igor Mammedov
@ 2026-05-26 14:42 ` Eric Auger
0 siblings, 0 replies; 57+ messages in thread
From: Eric Auger @ 2026-05-26 14:42 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> tests/qtest/bios-tables-test-allowed-diff.h | 1 +
> tests/data/acpi/aarch64/virt/WDAT.wdat | 0
> 2 files changed, 1 insertion(+)
> create mode 100644 tests/data/acpi/aarch64/virt/WDAT.wdat
>
> diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
> index dfb8523c8b..135186b40b 100644
> --- a/tests/qtest/bios-tables-test-allowed-diff.h
> +++ b/tests/qtest/bios-tables-test-allowed-diff.h
> @@ -1 +1,2 @@
> /* List of comma-separated changed AML files to ignore */
> +"tests/data/acpi/aarch64/virt/WDAT.wdat",
> diff --git a/tests/data/acpi/aarch64/virt/WDAT.wdat b/tests/data/acpi/aarch64/virt/WDAT.wdat
> new file mode 100644
> index 0000000000..e69de29bb2
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 13/21] tests: acpi: arm/virt: add WDAT table test case
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (11 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 12/21] tests: acpi: arm/virt: whitelist new WDAT table Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 14/21] tests: acpi: arm/virt: update expected WDAT blob Igor Mammedov
` (9 subsequent siblings)
22 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
tests/qtest/bios-tables-test.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 5b01a657e5..5082866184 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -2271,6 +2271,25 @@ static void test_acpi_aarch64_virt_tcg_msi_gicv2m(void)
free_test_data(&data);
}
+static void test_acpi_aarch64_virt_tcg_wdat(void)
+{
+ test_data data = {
+ .machine = "virt",
+ .arch = "aarch64",
+ .variant = ".wdat",
+ .tcg_only = true,
+ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
+ .ram_start = 0x40000000ULL,
+ .scan_len = 128ULL * MiB,
+ };
+
+ test_acpi_one("-cpu cortex-a57 "
+ "-device sbsa_gwdt,wdat=on", &data);
+ free_test_data(&data);
+}
+
static void test_acpi_q35_viot(void)
{
test_data data = {
@@ -2889,6 +2908,8 @@ int main(int argc, char *argv[])
qtest_add_func("acpi/virt/smmuv3-dev",
test_acpi_aarch64_virt_smmuv3_dev);
}
+ qtest_add_func("acpi/virt/acpi-watchdog",
+ test_acpi_aarch64_virt_tcg_wdat);
}
} else if (strcmp(arch, "riscv64") == 0) {
if (has_tcg && qtest_has_device("virtio-blk-pci")) {
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH v2 14/21] tests: acpi: arm/virt: update expected WDAT blob
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (12 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 13/21] tests: acpi: arm/virt: add WDAT table test case Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 15/21] tests: acpi: arm/virt: whitelist GTDT table Igor Mammedov
` (8 subsequent siblings)
22 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
replace blank table with a new one:
[000h 0000 004h] Signature : "WDAT" [Watchdog Action Table]
[004h 0004 004h] Table Length : 00000104
[008h 0008 001h] Revision : 01
[009h 0009 001h] Checksum : 3B
[00Ah 0010 006h] Oem ID : "BOCHS "
[010h 0016 008h] Oem Table ID : "BXPC "
[018h 0024 004h] Oem Revision : 00000001
[01Ch 0028 004h] Asl Compiler ID : "BXPC"
[020h 0032 004h] Asl Compiler Revision : 00000001
[024h 0036 004h] Header Length : 00000020
[028h 0040 002h] PCI Segment : 00FF
[02Ah 0042 001h] PCI Bus : FF
[02Bh 0043 001h] PCI Device : FF
[02Ch 0044 001h] PCI Function : FF
[02Dh 0045 003h] Reserved : 000000
[030h 0048 004h] Timer Period : 00000001
[034h 0052 004h] Max Count : 000927C0
[038h 0056 004h] Min Count : 00001388
[03Ch 0060 001h] Flags (decoded below) : 81
Enabled : 1
Stopped When Asleep : 1
[03Dh 0061 003h] Reserved : 000000
[040h 0064 004h] Watchdog Entry Count : 00000008
[044h 0068 001h] Watchdog Action : 08
[045h 0069 001h] Instruction : 00
[046h 0070 002h] Reserved : 0000
[048h 0072 00Ch] Register Region : [Generic Address Structure]
[048h 0072 001h] Space ID : 00 [SystemMemory]
[049h 0073 001h] Bit Width : 20
[04Ah 0074 001h] Bit Offset : 00
[04Bh 0075 001h] Encoded Access Width : 03 [DWord Access:32]
[04Ch 0076 008h] Address : 000000000C001000
[054h 0084 004h] Value : 00000001
[058h 0088 004h] Register Mask : 00000001
[05Ch 0092 001h] Watchdog Action : 01
[05Dh 0093 001h] Instruction : 02
[05Eh 0094 002h] Reserved : 0000
[060h 0096 00Ch] Register Region : [Generic Address Structure]
[060h 0096 001h] Space ID : 00 [SystemMemory]
[061h 0097 001h] Bit Width : 20
[062h 0098 001h] Bit Offset : 00
[063h 0099 001h] Encoded Access Width : 03 [DWord Access:32]
[064h 0100 008h] Address : 000000000C000000
[06Ch 0108 004h] Value : 00000001
[070h 0112 004h] Register Mask : 00000007
[074h 0116 001h] Watchdog Action : 06
[075h 0117 001h] Instruction : 03
[076h 0118 002h] Reserved : 0000
[078h 0120 00Ch] Register Region : [Generic Address Structure]
[078h 0120 001h] Space ID : 00 [SystemMemory]
[079h 0121 001h] Bit Width : 20
[07Ah 0122 001h] Bit Offset : 00
[07Bh 0123 001h] Encoded Access Width : 03 [DWord Access:32]
[07Ch 0124 008h] Address : 000000000C001008
[084h 0132 004h] Value : 00000000
[088h 0136 004h] Register Mask : FFFFFFFF
[08Ch 0140 001h] Watchdog Action : 09
[08Dh 0141 001h] Instruction : 82
[08Eh 0142 002h] Reserved : 0000
[090h 0144 00Ch] Register Region : [Generic Address Structure]
[090h 0144 001h] Space ID : 00 [SystemMemory]
[091h 0145 001h] Bit Width : 20
[092h 0146 001h] Bit Offset : 00
[093h 0147 001h] Encoded Access Width : 03 [DWord Access:32]
[094h 0148 008h] Address : 000000000C001000
[09Ch 0156 004h] Value : 00000001
[0A0h 0160 004h] Register Mask : 00000001
[0A4h 0164 001h] Watchdog Action : 0A
[0A5h 0165 001h] Instruction : 00
[0A6h 0166 002h] Reserved : 0000
[0A8h 0168 00Ch] Register Region : [Generic Address Structure]
[0A8h 0168 001h] Space ID : 00 [SystemMemory]
[0A9h 0169 001h] Bit Width : 20
[0AAh 0170 001h] Bit Offset : 00
[0ABh 0171 001h] Encoded Access Width : 03 [DWord Access:32]
[0ACh 0172 008h] Address : 000000000C001000
[0B4h 0180 004h] Value : 00000000
[0B8h 0184 004h] Register Mask : 00000001
[0BCh 0188 001h] Watchdog Action : 0B
[0BDh 0189 001h] Instruction : 82
[0BEh 0190 002h] Reserved : 0000
[0C0h 0192 00Ch] Register Region : [Generic Address Structure]
[0C0h 0192 001h] Space ID : 00 [SystemMemory]
[0C1h 0193 001h] Bit Width : 20
[0C2h 0194 001h] Bit Offset : 00
[0C3h 0195 001h] Encoded Access Width : 03 [DWord Access:32]
[0C4h 0196 008h] Address : 000000000C001000
[0CCh 0204 004h] Value : 00000000
[0D0h 0208 004h] Register Mask : 00000001
[0D4h 0212 001h] Watchdog Action : 20
[0D5h 0213 001h] Instruction : 00
[0D6h 0214 002h] Reserved : 0000
[0D8h 0216 00Ch] Register Region : [Generic Address Structure]
[0D8h 0216 001h] Space ID : 00 [SystemMemory]
[0D9h 0217 001h] Bit Width : 20
[0DAh 0218 001h] Bit Offset : 00
[0DBh 0219 001h] Encoded Access Width : 03 [DWord Access:32]
[0DCh 0220 008h] Address : 000000000C001000
[0E4h 0228 004h] Value : 00000004
[0E8h 0232 004h] Register Mask : 00000004
[0ECh 0236 001h] Watchdog Action : 21
[0EDh 0237 001h] Instruction : 82
[0EEh 0238 002h] Reserved : 0000
[0F0h 0240 00Ch] Register Region : [Generic Address Structure]
[0F0h 0240 001h] Space ID : 00 [SystemMemory]
[0F1h 0241 001h] Bit Width : 20
[0F2h 0242 001h] Bit Offset : 00
[0F3h 0243 001h] Encoded Access Width : 03 [DWord Access:32]
[0F4h 0244 008h] Address : 000000000C000000
[0FCh 0252 004h] Value : 00000004
[100h 0256 004h] Register Mask : 00000004
Raw Table Data: Length 260 (0x104)
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 -
tests/data/acpi/aarch64/virt/WDAT.wdat | Bin 0 -> 260 bytes
2 files changed, 1 deletion(-)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index 135186b40b..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,2 +1 @@
/* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/aarch64/virt/WDAT.wdat",
diff --git a/tests/data/acpi/aarch64/virt/WDAT.wdat b/tests/data/acpi/aarch64/virt/WDAT.wdat
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..81786ab0968a5c2004fcf3eee5ec443525c98c3e 100644
GIT binary patch
literal 260
zcmZ9GK?=f93`F1e7j4yr;05B!L%3?|!kvPGUPo6wmN$z`$;Z+_NHV+(^E|hYDnUAR
z*Zy+1?se<U%o3no(*Vca0o~tY!?1@pP)B2Ac5DeoTw09J8UFeTSV}Q+9lXljz4-(`
b^H~d+_^af<nejze-YH+f*oVSLo}&K%0}B)Z
literal 0
HcmV?d00001
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH v2 15/21] tests: acpi: arm/virt: whitelist GTDT table
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (13 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 14/21] tests: acpi: arm/virt: update expected WDAT blob Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-26 14:42 ` Eric Auger
2026-03-03 9:25 ` [PATCH v2 16/21] tests: acpi: arm/virt: add GTDT watchdog table test case Igor Mammedov
` (7 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..3e9be28cc4 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,2 @@
/* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/aarch64/virt/GTDT",
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 15/21] tests: acpi: arm/virt: whitelist GTDT table
2026-03-03 9:25 ` [PATCH v2 15/21] tests: acpi: arm/virt: whitelist GTDT table Igor Mammedov
@ 2026-05-26 14:42 ` Eric Auger
0 siblings, 0 replies; 57+ messages in thread
From: Eric Auger @ 2026-05-26 14:42 UTC (permalink / raw)
To: qemu-devel
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> tests/qtest/bios-tables-test-allowed-diff.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
> index dfb8523c8b..3e9be28cc4 100644
> --- a/tests/qtest/bios-tables-test-allowed-diff.h
> +++ b/tests/qtest/bios-tables-test-allowed-diff.h
> @@ -1 +1,2 @@
> /* List of comma-separated changed AML files to ignore */
> +"tests/data/acpi/aarch64/virt/GTDT",
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 16/21] tests: acpi: arm/virt: add GTDT watchdog table test case
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (14 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 15/21] tests: acpi: arm/virt: whitelist GTDT table Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-26 14:44 ` Eric Auger
2026-03-03 9:25 ` [PATCH v2 17/21] tests: acpi: arm/virt: update expected GTDT blob Igor Mammedov
` (6 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
tests/qtest/bios-tables-test.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 5082866184..11c6854af8 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -2290,6 +2290,24 @@ static void test_acpi_aarch64_virt_tcg_wdat(void)
free_test_data(&data);
}
+static void test_acpi_aarch64_virt_tcg_gtdt_wd(void)
+{
+ test_data data = {
+ .machine = "virt",
+ .arch = "aarch64",
+ .variant = ".gwdt",
+ .tcg_only = true,
+ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
+ .ram_start = 0x40000000ULL,
+ .scan_len = 128ULL * MiB,
+ };
+
+ test_acpi_one("-cpu cortex-a57 " "-device sbsa_gwdt", &data);
+ free_test_data(&data);
+}
+
static void test_acpi_q35_viot(void)
{
test_data data = {
@@ -2910,6 +2928,8 @@ int main(int argc, char *argv[])
}
qtest_add_func("acpi/virt/acpi-watchdog",
test_acpi_aarch64_virt_tcg_wdat);
+ qtest_add_func("acpi/virt/gwdt-watchdog",
+ test_acpi_aarch64_virt_tcg_gtdt_wd);
}
} else if (strcmp(arch, "riscv64") == 0) {
if (has_tcg && qtest_has_device("virtio-blk-pci")) {
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 16/21] tests: acpi: arm/virt: add GTDT watchdog table test case
2026-03-03 9:25 ` [PATCH v2 16/21] tests: acpi: arm/virt: add GTDT watchdog table test case Igor Mammedov
@ 2026-05-26 14:44 ` Eric Auger
2026-05-27 12:58 ` Igor Mammedov
0 siblings, 1 reply; 57+ messages in thread
From: Eric Auger @ 2026-05-26 14:44 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> tests/qtest/bios-tables-test.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
> index 5082866184..11c6854af8 100644
> --- a/tests/qtest/bios-tables-test.c
> +++ b/tests/qtest/bios-tables-test.c
> @@ -2290,6 +2290,24 @@ static void test_acpi_aarch64_virt_tcg_wdat(void)
> free_test_data(&data);
> }
>
> +static void test_acpi_aarch64_virt_tcg_gtdt_wd(void)
> +{
> + test_data data = {
> + .machine = "virt",
> + .arch = "aarch64",
> + .variant = ".gwdt",
> + .tcg_only = true,
> + .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
> + .uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
> + .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
> + .ram_start = 0x40000000ULL,
> + .scan_len = 128ULL * MiB,
> + };
> +
> + test_acpi_one("-cpu cortex-a57 " "-device sbsa_gwdt", &data);
depends on the instantiation strategy, ie. whether Peter is OK with
dynamic sysbus instantiation
Thanks
Eric
> + free_test_data(&data);
> +}
> +
> static void test_acpi_q35_viot(void)
> {
> test_data data = {
> @@ -2910,6 +2928,8 @@ int main(int argc, char *argv[])
> }
> qtest_add_func("acpi/virt/acpi-watchdog",
> test_acpi_aarch64_virt_tcg_wdat);
> + qtest_add_func("acpi/virt/gwdt-watchdog",
> + test_acpi_aarch64_virt_tcg_gtdt_wd);
> }
> } else if (strcmp(arch, "riscv64") == 0) {
> if (has_tcg && qtest_has_device("virtio-blk-pci")) {
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 16/21] tests: acpi: arm/virt: add GTDT watchdog table test case
2026-05-26 14:44 ` Eric Auger
@ 2026-05-27 12:58 ` Igor Mammedov
0 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-05-27 12:58 UTC (permalink / raw)
To: Eric Auger
Cc: qemu-devel, mst, anisinha, pbonzini, peter.maydell,
shannon.zhaosl, philmd, zhao1.liu, rad, leif.lindholm, qemu-arm
On Tue, 26 May 2026 16:44:08 +0200
Eric Auger <eauger@redhat.com> wrote:
> On 3/3/26 10:25 AM, Igor Mammedov wrote:
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > tests/qtest/bios-tables-test.c | 20 ++++++++++++++++++++
> > 1 file changed, 20 insertions(+)
> >
> > diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
> > index 5082866184..11c6854af8 100644
> > --- a/tests/qtest/bios-tables-test.c
> > +++ b/tests/qtest/bios-tables-test.c
> > @@ -2290,6 +2290,24 @@ static void test_acpi_aarch64_virt_tcg_wdat(void)
> > free_test_data(&data);
> > }
> >
> > +static void test_acpi_aarch64_virt_tcg_gtdt_wd(void)
> > +{
> > + test_data data = {
> > + .machine = "virt",
> > + .arch = "aarch64",
> > + .variant = ".gwdt",
> > + .tcg_only = true,
> > + .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
> > + .uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
> > + .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
> > + .ram_start = 0x40000000ULL,
> > + .scan_len = 128ULL * MiB,
> > + };
> > +
> > + test_acpi_one("-cpu cortex-a57 " "-device sbsa_gwdt", &data);
> depends on the instantiation strategy, ie. whether Peter is OK with
> dynamic sysbus instantiation
machine option in v1 to do the same opened another can of worms
that I think consensus was it would be better go with -device.
>
> Thanks
>
> Eric
> > + free_test_data(&data);
> > +}
> > +
> > static void test_acpi_q35_viot(void)
> > {
> > test_data data = {
> > @@ -2910,6 +2928,8 @@ int main(int argc, char *argv[])
> > }
> > qtest_add_func("acpi/virt/acpi-watchdog",
> > test_acpi_aarch64_virt_tcg_wdat);
> > + qtest_add_func("acpi/virt/gwdt-watchdog",
> > + test_acpi_aarch64_virt_tcg_gtdt_wd);
> > }
> > } else if (strcmp(arch, "riscv64") == 0) {
> > if (has_tcg && qtest_has_device("virtio-blk-pci")) {
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 17/21] tests: acpi: arm/virt: update expected GTDT blob
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (15 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 16/21] tests: acpi: arm/virt: add GTDT watchdog table test case Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 18/21] sbsa_gwdt: reduce code ident Igor Mammedov
` (5 subsequent siblings)
22 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Expected diff from base GTDT is an addition of watchdog
timer block:
[000h 0000 004h] Signature : "GTDT" [Generic Timer Description Table]
-[004h 0004 004h] Table Length : 00000068
+[004h 0004 004h] Table Length : 00000084
[008h 0008 001h] Revision : 03
-[009h 0009 001h] Checksum : 93
+[009h 0009 001h] Checksum : 39
[00Ah 0010 006h] Oem ID : "BOCHS "
[010h 0016 008h] Oem Table ID : "BXPC "
[018h 0024 004h] Oem Revision : 00000001
@@ -48,17 +48,30 @@
Always On : 0
[050h 0080 008h] Counter Read Block Address : FFFFFFFFFFFFFFFF
-[058h 0088 004h] Platform Timer Count : 00000000
-[05Ch 0092 004h] Platform Timer Offset : 00000000
+[058h 0088 004h] Platform Timer Count : 00000001
+[05Ch 0092 004h] Platform Timer Offset : 00000068
[060h 0096 004h] Virtual EL2 Timer GSIV : 00000000
[064h 0100 004h] Virtual EL2 Timer Flags : 00000000
-Raw Table Data: Length 104 (0x68)
+[068h 0104 001h] Subtable Type : 01 [Generic Watchdog Timer]
+[069h 0105 002h] Length : 001C
+[06Bh 0107 001h] Reserved : 00
+[06Ch 0108 008h] Refresh Frame Address : 000000000C000000
+[074h 0116 008h] Control Frame Address : 000000000C001000
+[07Ch 0124 004h] Timer Interrupt : 00000090
+[080h 0128 004h] Timer Flags (decoded below) : 00000000
+ Trigger Mode : 0
+ Polarity : 0
+ Security : 0
+
+Raw Table Data: Length 132 (0x84)
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
tests/qtest/bios-tables-test-allowed-diff.h | 1 -
tests/data/acpi/aarch64/virt/GTDT.gwdt | Bin 0 -> 132 bytes
2 files changed, 1 deletion(-)
create mode 100644 tests/data/acpi/aarch64/virt/GTDT.gwdt
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h
index 3e9be28cc4..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,2 +1 @@
/* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/aarch64/virt/GTDT",
diff --git a/tests/data/acpi/aarch64/virt/GTDT.gwdt b/tests/data/acpi/aarch64/virt/GTDT.gwdt
new file mode 100644
index 0000000000000000000000000000000000000000..e0c2151fa7d3432740bb997d7d33669e30f133aa
GIT binary patch
literal 132
zcmZ<{aS3T*U|?Xjbn<uh2v%^42yj+VP*7lGU|;~TLG*tpU|?WikOdJ83=DD%3=Av`
i3=Gmxz7&*(sRilFfQo?tqYRkh0h0m{dIFfkzyJV@>lgt5
literal 0
HcmV?d00001
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH v2 18/21] sbsa_gwdt: reduce code ident
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (16 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 17/21] tests: acpi: arm/virt: update expected GTDT blob Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-05-26 14:37 ` Eric Auger
2026-03-03 9:25 ` [PATCH v2 19/21] sbsa_gwdt: move all foo_REFRESH logic under REFRESH condition Igor Mammedov
` (4 subsequent siblings)
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
hw/watchdog/sbsa_gwdt.c | 38 ++++++++++++++++++++------------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index 40d80f7f2b..91f9a4202c 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -105,25 +105,27 @@ static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
timer_del(s->timer);
- if (s->wcs & SBSA_GWDT_WCS_EN) {
- /*
- * Extract the upper 16 bits from woru & 32 bits from worl
- * registers to construct the 48 bit offset value
- */
- timeout = s->woru;
- timeout <<= 32;
- timeout |= s->worl;
- timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq);
- timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
- if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
- (!(s->wcs & SBSA_GWDT_WCS_WS0)))) {
- /* store the current timeout value into compare registers */
- s->wcvu = timeout >> 32;
- s->wcvl = timeout;
- }
- timer_mod(s->timer, timeout);
+ if (!(s->wcs & SBSA_GWDT_WCS_EN)) {
+ return;
+ }
+
+ /*
+ * Extract the upper 16 bits from woru & 32 bits from worl
+ * registers to construct the 48 bit offset value
+ */
+ timeout = s->woru;
+ timeout <<= 32;
+ timeout |= s->worl;
+ timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq);
+ timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+
+ if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
+ (!(s->wcs & SBSA_GWDT_WCS_WS0)))) {
+ /* store the current timeout value into compare registers */
+ s->wcvu = timeout >> 32;
+ s->wcvl = timeout;
}
+ timer_mod(s->timer, timeout);
}
static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data,
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 18/21] sbsa_gwdt: reduce code ident
2026-03-03 9:25 ` [PATCH v2 18/21] sbsa_gwdt: reduce code ident Igor Mammedov
@ 2026-05-26 14:37 ` Eric Auger
0 siblings, 0 replies; 57+ messages in thread
From: Eric Auger @ 2026-05-26 14:37 UTC (permalink / raw)
To: Igor Mammedov, qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On 3/3/26 10:25 AM, Igor Mammedov wrote:
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Eric
> ---
> hw/watchdog/sbsa_gwdt.c | 38 ++++++++++++++++++++------------------
> 1 file changed, 20 insertions(+), 18 deletions(-)
>
> diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
> index 40d80f7f2b..91f9a4202c 100644
> --- a/hw/watchdog/sbsa_gwdt.c
> +++ b/hw/watchdog/sbsa_gwdt.c
> @@ -105,25 +105,27 @@ static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
>
> timer_del(s->timer);
>
> - if (s->wcs & SBSA_GWDT_WCS_EN) {
> - /*
> - * Extract the upper 16 bits from woru & 32 bits from worl
> - * registers to construct the 48 bit offset value
> - */
> - timeout = s->woru;
> - timeout <<= 32;
> - timeout |= s->worl;
> - timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq);
> - timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> -
> - if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
> - (!(s->wcs & SBSA_GWDT_WCS_WS0)))) {
> - /* store the current timeout value into compare registers */
> - s->wcvu = timeout >> 32;
> - s->wcvl = timeout;
> - }
> - timer_mod(s->timer, timeout);
> + if (!(s->wcs & SBSA_GWDT_WCS_EN)) {
> + return;
> + }
> +
> + /*
> + * Extract the upper 16 bits from woru & 32 bits from worl
> + * registers to construct the 48 bit offset value
> + */
> + timeout = s->woru;
> + timeout <<= 32;
> + timeout |= s->worl;
> + timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq);
> + timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +
> + if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
> + (!(s->wcs & SBSA_GWDT_WCS_WS0)))) {
> + /* store the current timeout value into compare registers */
> + s->wcvu = timeout >> 32;
> + s->wcvl = timeout;
> }
> + timer_mod(s->timer, timeout);
> }
>
> static void sbsa_gwdt_rwrite(void *opaque, hwaddr offset, uint64_t data,
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH v2 19/21] sbsa_gwdt: move all foo_REFRESH logic under REFRESH condition
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (17 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 18/21] sbsa_gwdt: reduce code ident Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 20/21] sbsa_gwdt: reschedule timer on direct WCV load Igor Mammedov
` (3 subsequent siblings)
22 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
and while at it, simplify timeout calculations
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
hw/watchdog/sbsa_gwdt.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index 91f9a4202c..c2d6f672f9 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -109,22 +109,20 @@ static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
return;
}
- /*
- * Extract the upper 16 bits from woru & 32 bits from worl
- * registers to construct the 48 bit offset value
- */
- timeout = s->woru;
- timeout <<= 32;
- timeout |= s->worl;
- timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq);
- timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) &&
(!(s->wcs & SBSA_GWDT_WCS_WS0)))) {
- /* store the current timeout value into compare registers */
+ uint64_t offset = (uint64_t)s->woru << 32 | s->worl;
+ timeout = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ muldiv64(offset, NANOSECONDS_PER_SECOND, s->freq);
+
+ /* store (now + offset)ns in WCV */
s->wcvu = timeout >> 32;
s->wcvl = timeout;
+ } else {
+ g_assert_not_reached();
}
+
+ timeout = (uint64_t)s->wcvu << 32 | s->wcvl;
timer_mod(s->timer, timeout);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH v2 20/21] sbsa_gwdt: reschedule timer on direct WCV load
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (18 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 19/21] sbsa_gwdt: move all foo_REFRESH logic under REFRESH condition Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-03-03 9:25 ` [PATCH v2 21/21] sbsa_gwdt: limit compare_value to INT64_MAX Igor Mammedov
` (2 subsequent siblings)
22 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
According to spec[1]
"The compare value can either be loaded directly or indirectly on an
explicit refresh or timeout refresh"
while QEMU does allow to write WCV, it doesn't act on
new value, which it should do according to pseudo code in spec:
"TimeoutRefresh = ( SystemCounter [63:0] > CompareValue [63:0])"
fix it by updating timer on WCV write.
Fixes Windows watchdog reboots, since it sets
WOR to ~4sec && never triggers WRR refresh
it however writes insane lage value into WCV
right after WOR & WCS enable, which effectively
cancels too small WOR value and missing WRR.
1) Arm® Server Base System Architecture 6.0
Platform Design Document
DEN0029D 6.0
"A.2 Watchdog Operation"
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
hw/watchdog/sbsa_gwdt.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index c2d6f672f9..7fec61b7b0 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -44,6 +44,7 @@ static const VMStateDescription vmstate_sbsa_gwdt = {
typedef enum WdtRefreshType {
EXPLICIT_REFRESH = 0,
TIMEOUT_REFRESH = 1,
+ WCV_LOAD = 2,
} WdtRefreshType;
static uint64_t sbsa_gwdt_rread(void *opaque, hwaddr addr, unsigned int size)
@@ -118,8 +119,6 @@ static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
/* store (now + offset)ns in WCV */
s->wcvu = timeout >> 32;
s->wcvl = timeout;
- } else {
- g_assert_not_reached();
}
timeout = (uint64_t)s->wcvu << 32 | s->wcvl;
@@ -169,10 +168,16 @@ static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data,
case SBSA_GWDT_WCV:
s->wcvl = data;
+ if (s->wcs & SBSA_GWDT_WCS_EN) {
+ sbsa_gwdt_update_timer(s, WCV_LOAD);
+ }
break;
case SBSA_GWDT_WCVU:
s->wcvu = data;
+ if (s->wcs & SBSA_GWDT_WCS_EN) {
+ sbsa_gwdt_update_timer(s, WCV_LOAD);
+ }
break;
default:
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH v2 21/21] sbsa_gwdt: limit compare_value to INT64_MAX
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (19 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 20/21] sbsa_gwdt: reschedule timer on direct WCV load Igor Mammedov
@ 2026-03-03 9:25 ` Igor Mammedov
2026-04-28 14:12 ` [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
2026-06-03 6:17 ` Michael S. Tsirkin
22 siblings, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-03-03 9:25 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
QEMU timer subsytem supports timeouts only upto INT64_MAX.
However WCV value geater than that will cause integer overflow
and timer will fire/expire immediately.
It looks like Windows tries to use SBSA watchdog when it's
exposed in GTDT ACPI table.
But instead of using WRR to refresh WCV with configured WOR,
it does direct load into WCV (probably as a means to
reschedule timer). While it's not against spec,
Windows does write following values:
sbsa_gwdt_control_write [0x8] <- 0xffffffff
sbsa_gwdt_control_write [0x0] <- 0x1
sbsa_gwdt_control_write [0x14] <- 0xffffffff
sbsa_gwdt_control_write [0x10] <- 0xa906ca28
sbsa_gwdt_control_write [0x14] <- 0xecb1
1st intermediate write into 0x14 (WCVU),
puts WCV into timer overflow range,
triggering TimeoutRefresh and WS0 and WS1 asseritons.
Clamp WCV to INT64_MAX to avoid timer API overflow.
It prevents unexpected Windows reboots by watchdog.
PS:
Arguably Windows SBSA GWDT driver is broken,
as it:
* sets WCV too far in the future so watchdog
would never trigger in practice,
* and typical watchdog flow for explict referesh
also broken due to:
1. small WOR value for explicit refresh (~4sec)
2. never triggering explicit refresh (WRR or other)
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
hw/watchdog/sbsa_gwdt.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index 7fec61b7b0..b1bce5008d 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -122,6 +122,8 @@ static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype)
}
timeout = (uint64_t)s->wcvu << 32 | s->wcvl;
+ /* clamp timeout to INT64_MAX to avoid timer overflow */
+ timeout &= INT64_MAX;
timer_mod(s->timer, timeout);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 57+ messages in thread* Re: [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (20 preceding siblings ...)
2026-03-03 9:25 ` [PATCH v2 21/21] sbsa_gwdt: limit compare_value to INT64_MAX Igor Mammedov
@ 2026-04-28 14:12 ` Igor Mammedov
2026-05-12 13:30 ` Igor Mammedov
2026-06-03 6:17 ` Michael S. Tsirkin
22 siblings, 1 reply; 57+ messages in thread
From: Igor Mammedov @ 2026-04-28 14:12 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On Tue, 3 Mar 2026 10:25:11 +0100
Igor Mammedov <imammedo@redhat.com> wrote:
> Changelog:
> v2:
> * ditch generic '-machine acpi-watchdog' option in favor of
> board specific variants:
> x86/q35: -machine wdat={on|off}
> arm/virt: -device sbsa_gwdt,wdat={on|off}
> * arm/virt: add FDT and GTDT ACPI entries for GWDT when it's present
> and hide GDTD one when WDAT is enabled.
> * arm/virt: add test case for GTDT
> * [18-21] optional GWDT cleanup/fixes in handling WCV register update,
> make QEMU behave according to spec (at least the way I read it and
> it appears MS also read it that way). It fixes Windows 11 reboots when
> GWDT is present (without WDAT). With that fixed it's up to MS to fix
> their driver to set sane timeout as with the current one wdatchdog
> will never trigger.
given merge window should be open by now,
gentle ping
> Windows doesn't ship built-in TCO watchdog driver, and users are
> forced to install vendor specific driver(s) if such exists.
> However the OS provides a generic watchdog driver that uses
> ACPI WDAT table [1] to abstract actual hardware behind it.
> The same applies to ARM version of Windows.
>
> This series adds
> * WDAT table tailored for TCO watchdog that Q35 already
> has as part of ICH9 chipset and a knob to enable it.
> * SBSA GWDT to arm/virt machine with WDAT table tailored
> for it and necessary tweaks to GWDT to make usable
> with WDAT driver.
> * in addition to WDAT, it also adds native variant
> with GWDT described in FDT and DTDT
> (broken on Windows/works on linux).
>
> Guest OS WDAT support is present since Windows Vista and Linux since 2016[2].
>
> One can test it launching VM with following options:
> * x86:
> -machine q35,wdat=on
> * arm/virt:
> -device sbsa_gwdt,wdat=on
>
> to trace access to TCO registers one can add to CLI:
> -trace "tco_*"
> to trace access to GWDT registers one can add to CLI:
> -trace "sbsa_gwdt*"
>
> To verify that guest uses WDAT (both Windows and Linux would use it if present),
> * on linux make sure that watchdog service is configured/enabled
> (use wdctl to check what watchdog device is in use) and then
> trigger kernel panic with command:
> echo c > /proc/sysrq-trigger
> * on Windows kill svchost process, running cmd in admin mode:
> taskkill /f /im svchost.exe
>
> Tested with WS2025 & RHEL9.6 & Fedora 43 (aarch64)
>
> git tree at: https://gitlab.com/imammedo/qemu/-/commits/gwdt_v2
>
> 1) http://msdn.microsoft.com/en-us/windows/hardware/gg463320.aspx
> 2) https://lwn.net/Articles/700524/
>
> PS:
> previous revision:
> https://patchew.org/QEMU/20260206131438.1857182-1-imammedo@redhat.com/
>
> Igor Mammedov (21):
> acpi: add API to build WDAT instructions
> x86: q35: add 'wdat' property
> x86: q35: generate WDAT ACPI table
> tests: acpi: x86/q35: whitelist new WDAT table
> tests: acpi: x86/q35: add WDAT table test case
> tests: acpi: x86/q35: update expected WDAT blob
> arm: sbsa_gwdt: fixup default "clock-frequency"
> arm: add tracing events to sbsa_gwdt
> arm: virt: create sbsa_gwdt watchdog
> arm: sbsa_gwdt: add 'wdat' option
> arm: virt: add support for WDAT based watchdog
> tests: acpi: arm/virt: whitelist new WDAT table
> tests: acpi: arm/virt: add WDAT table test case
> tests: acpi: arm/virt: update expected WDAT blob
> tests: acpi: arm/virt: whitelist GTDT table
> tests: acpi: arm/virt: add GTDT watchdog table test case
> tests: acpi: arm/virt: update expected GTDT blob
> sbsa_gwdt: reduce code ident
> sbsa_gwdt: move all foo_REFRESH logic under REFRESH condition
> sbsa_gwdt: reschedule timer on direct WCV load
> sbsa_gwdt: limit compare_value to INT64_MAX
>
> include/hw/acpi/wdat-gwdt.h | 19 ++++
> include/hw/acpi/wdat-ich9.h | 15 ++++
> include/hw/acpi/wdat.h | 118 +++++++++++++++++++++++++
> include/hw/i386/pc.h | 1 +
> include/hw/watchdog/sbsa_gwdt.h | 1 +
> hw/acpi/aml-build.c | 14 +++
> hw/acpi/meson.build | 5 +-
> hw/acpi/wdat-gwdt-stub.c | 16 ++++
> hw/acpi/wdat-gwdt.c | 92 +++++++++++++++++++
> hw/acpi/wdat-ich9-stub.c | 15 ++++
> hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++
> hw/arm/Kconfig | 1 +
> hw/arm/virt-acpi-build.c | 65 +++++++++++++-
> hw/arm/virt.c | 2 +
> hw/core/sysbus-fdt.c | 32 +++++++
> hw/i386/acpi-build.c | 12 +++
> hw/i386/pc_q35.c | 18 ++++
> hw/watchdog/sbsa_gwdt.c | 65 +++++++++-----
> hw/watchdog/trace-events | 9 ++
> tests/data/acpi/aarch64/virt/GTDT.gwdt | Bin 0 -> 132 bytes
> tests/data/acpi/aarch64/virt/WDAT.wdat | Bin 0 -> 260 bytes
> tests/data/acpi/x86/q35/WDAT.wdat | Bin 0 -> 308 bytes
> tests/qtest/bios-tables-test.c | 54 +++++++++++
> 23 files changed, 618 insertions(+), 26 deletions(-)
> create mode 100644 include/hw/acpi/wdat-gwdt.h
> create mode 100644 include/hw/acpi/wdat-ich9.h
> create mode 100644 include/hw/acpi/wdat.h
> create mode 100644 hw/acpi/wdat-gwdt-stub.c
> create mode 100644 hw/acpi/wdat-gwdt.c
> create mode 100644 hw/acpi/wdat-ich9-stub.c
> create mode 100644 hw/acpi/wdat-ich9.c
> create mode 100644 tests/data/acpi/aarch64/virt/GTDT.gwdt
> create mode 100644 tests/data/acpi/aarch64/virt/WDAT.wdat
> create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards
2026-04-28 14:12 ` [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
@ 2026-05-12 13:30 ` Igor Mammedov
2026-05-12 14:45 ` Ani Sinha
2026-05-18 14:35 ` Igor Mammedov
0 siblings, 2 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-05-12 13:30 UTC (permalink / raw)
To: qemu-devel
Cc: mst, anisinha, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On Tue, 28 Apr 2026 16:12:15 +0200
Igor Mammedov <imammedo@redhat.com> wrote:
> On Tue, 3 Mar 2026 10:25:11 +0100
> Igor Mammedov <imammedo@redhat.com> wrote:
>
> > Changelog:
> > v2:
> > * ditch generic '-machine acpi-watchdog' option in favor of
> > board specific variants:
> > x86/q35: -machine wdat={on|off}
> > arm/virt: -device sbsa_gwdt,wdat={on|off}
> > * arm/virt: add FDT and GTDT ACPI entries for GWDT when it's present
> > and hide GDTD one when WDAT is enabled.
> > * arm/virt: add test case for GTDT
> > * [18-21] optional GWDT cleanup/fixes in handling WCV register update,
> > make QEMU behave according to spec (at least the way I read it and
> > it appears MS also read it that way). It fixes Windows 11 reboots when
> > GWDT is present (without WDAT). With that fixed it's up to MS to fix
> > their driver to set sane timeout as with the current one wdatchdog
> > will never trigger.
>
> given merge window should be open by now,
> gentle ping
2 weeks later,
yet another ping
>
> > Windows doesn't ship built-in TCO watchdog driver, and users are
> > forced to install vendor specific driver(s) if such exists.
> > However the OS provides a generic watchdog driver that uses
> > ACPI WDAT table [1] to abstract actual hardware behind it.
> > The same applies to ARM version of Windows.
> >
> > This series adds
> > * WDAT table tailored for TCO watchdog that Q35 already
> > has as part of ICH9 chipset and a knob to enable it.
> > * SBSA GWDT to arm/virt machine with WDAT table tailored
> > for it and necessary tweaks to GWDT to make usable
> > with WDAT driver.
> > * in addition to WDAT, it also adds native variant
> > with GWDT described in FDT and DTDT
> > (broken on Windows/works on linux).
> >
> > Guest OS WDAT support is present since Windows Vista and Linux since 2016[2].
> >
> > One can test it launching VM with following options:
> > * x86:
> > -machine q35,wdat=on
> > * arm/virt:
> > -device sbsa_gwdt,wdat=on
> >
> > to trace access to TCO registers one can add to CLI:
> > -trace "tco_*"
> > to trace access to GWDT registers one can add to CLI:
> > -trace "sbsa_gwdt*"
> >
> > To verify that guest uses WDAT (both Windows and Linux would use it if present),
> > * on linux make sure that watchdog service is configured/enabled
> > (use wdctl to check what watchdog device is in use) and then
> > trigger kernel panic with command:
> > echo c > /proc/sysrq-trigger
> > * on Windows kill svchost process, running cmd in admin mode:
> > taskkill /f /im svchost.exe
> >
> > Tested with WS2025 & RHEL9.6 & Fedora 43 (aarch64)
> >
> > git tree at: https://gitlab.com/imammedo/qemu/-/commits/gwdt_v2
> >
> > 1) http://msdn.microsoft.com/en-us/windows/hardware/gg463320.aspx
> > 2) https://lwn.net/Articles/700524/
> >
> > PS:
> > previous revision:
> > https://patchew.org/QEMU/20260206131438.1857182-1-imammedo@redhat.com/
> >
> > Igor Mammedov (21):
> > acpi: add API to build WDAT instructions
> > x86: q35: add 'wdat' property
> > x86: q35: generate WDAT ACPI table
> > tests: acpi: x86/q35: whitelist new WDAT table
> > tests: acpi: x86/q35: add WDAT table test case
> > tests: acpi: x86/q35: update expected WDAT blob
> > arm: sbsa_gwdt: fixup default "clock-frequency"
> > arm: add tracing events to sbsa_gwdt
> > arm: virt: create sbsa_gwdt watchdog
> > arm: sbsa_gwdt: add 'wdat' option
> > arm: virt: add support for WDAT based watchdog
> > tests: acpi: arm/virt: whitelist new WDAT table
> > tests: acpi: arm/virt: add WDAT table test case
> > tests: acpi: arm/virt: update expected WDAT blob
> > tests: acpi: arm/virt: whitelist GTDT table
> > tests: acpi: arm/virt: add GTDT watchdog table test case
> > tests: acpi: arm/virt: update expected GTDT blob
> > sbsa_gwdt: reduce code ident
> > sbsa_gwdt: move all foo_REFRESH logic under REFRESH condition
> > sbsa_gwdt: reschedule timer on direct WCV load
> > sbsa_gwdt: limit compare_value to INT64_MAX
> >
> > include/hw/acpi/wdat-gwdt.h | 19 ++++
> > include/hw/acpi/wdat-ich9.h | 15 ++++
> > include/hw/acpi/wdat.h | 118 +++++++++++++++++++++++++
> > include/hw/i386/pc.h | 1 +
> > include/hw/watchdog/sbsa_gwdt.h | 1 +
> > hw/acpi/aml-build.c | 14 +++
> > hw/acpi/meson.build | 5 +-
> > hw/acpi/wdat-gwdt-stub.c | 16 ++++
> > hw/acpi/wdat-gwdt.c | 92 +++++++++++++++++++
> > hw/acpi/wdat-ich9-stub.c | 15 ++++
> > hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++
> > hw/arm/Kconfig | 1 +
> > hw/arm/virt-acpi-build.c | 65 +++++++++++++-
> > hw/arm/virt.c | 2 +
> > hw/core/sysbus-fdt.c | 32 +++++++
> > hw/i386/acpi-build.c | 12 +++
> > hw/i386/pc_q35.c | 18 ++++
> > hw/watchdog/sbsa_gwdt.c | 65 +++++++++-----
> > hw/watchdog/trace-events | 9 ++
> > tests/data/acpi/aarch64/virt/GTDT.gwdt | Bin 0 -> 132 bytes
> > tests/data/acpi/aarch64/virt/WDAT.wdat | Bin 0 -> 260 bytes
> > tests/data/acpi/x86/q35/WDAT.wdat | Bin 0 -> 308 bytes
> > tests/qtest/bios-tables-test.c | 54 +++++++++++
> > 23 files changed, 618 insertions(+), 26 deletions(-)
> > create mode 100644 include/hw/acpi/wdat-gwdt.h
> > create mode 100644 include/hw/acpi/wdat-ich9.h
> > create mode 100644 include/hw/acpi/wdat.h
> > create mode 100644 hw/acpi/wdat-gwdt-stub.c
> > create mode 100644 hw/acpi/wdat-gwdt.c
> > create mode 100644 hw/acpi/wdat-ich9-stub.c
> > create mode 100644 hw/acpi/wdat-ich9.c
> > create mode 100644 tests/data/acpi/aarch64/virt/GTDT.gwdt
> > create mode 100644 tests/data/acpi/aarch64/virt/WDAT.wdat
> > create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
> >
>
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards
2026-05-12 13:30 ` Igor Mammedov
@ 2026-05-12 14:45 ` Ani Sinha
2026-05-18 14:35 ` Igor Mammedov
1 sibling, 0 replies; 57+ messages in thread
From: Ani Sinha @ 2026-05-12 14:45 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, mst, pbonzini, peter.maydell, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
> On 12 May 2026, at 7:00 PM, Igor Mammedov <imammedo@redhat.com> wrote:
>
> On Tue, 28 Apr 2026 16:12:15 +0200
> Igor Mammedov <imammedo@redhat.com> wrote:
>
>> On Tue, 3 Mar 2026 10:25:11 +0100
>> Igor Mammedov <imammedo@redhat.com> wrote:
>>
>>> Changelog:
>>> v2:
>>> * ditch generic '-machine acpi-watchdog' option in favor of
>>> board specific variants:
>>> x86/q35: -machine wdat={on|off}
>>> arm/virt: -device sbsa_gwdt,wdat={on|off}
>>> * arm/virt: add FDT and GTDT ACPI entries for GWDT when it's present
>>> and hide GDTD one when WDAT is enabled.
>>> * arm/virt: add test case for GTDT
>>> * [18-21] optional GWDT cleanup/fixes in handling WCV register update,
>>> make QEMU behave according to spec (at least the way I read it and
>>> it appears MS also read it that way). It fixes Windows 11 reboots when
>>> GWDT is present (without WDAT). With that fixed it's up to MS to fix
>>> their driver to set sane timeout as with the current one wdatchdog
>>> will never trigger.
>>
>> given merge window should be open by now,
>> gentle ping
>
> 2 weeks later,
> yet another ping
I have this in my queue for review.
^ permalink raw reply [flat|nested] 57+ messages in thread* Re: [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards
2026-05-12 13:30 ` Igor Mammedov
2026-05-12 14:45 ` Ani Sinha
@ 2026-05-18 14:35 ` Igor Mammedov
1 sibling, 0 replies; 57+ messages in thread
From: Igor Mammedov @ 2026-05-18 14:35 UTC (permalink / raw)
To: peter.maydell
Cc: qemu-devel, mst, anisinha, pbonzini, shannon.zhaosl, philmd,
zhao1.liu, rad, leif.lindholm, qemu-arm
On Tue, 12 May 2026 15:30:57 +0200
Igor Mammedov <imammedo@redhat.com> wrote:
Peter,
could you take a look at ARM related patches,
I hope that I have addressed you concerns from v1.
> On Tue, 28 Apr 2026 16:12:15 +0200
> Igor Mammedov <imammedo@redhat.com> wrote:
>
> > On Tue, 3 Mar 2026 10:25:11 +0100
> > Igor Mammedov <imammedo@redhat.com> wrote:
> >
> > > Changelog:
> > > v2:
> > > * ditch generic '-machine acpi-watchdog' option in favor of
> > > board specific variants:
> > > x86/q35: -machine wdat={on|off}
> > > arm/virt: -device sbsa_gwdt,wdat={on|off}
> > > * arm/virt: add FDT and GTDT ACPI entries for GWDT when it's present
> > > and hide GDTD one when WDAT is enabled.
> > > * arm/virt: add test case for GTDT
> > > * [18-21] optional GWDT cleanup/fixes in handling WCV register update,
> > > make QEMU behave according to spec (at least the way I read it and
> > > it appears MS also read it that way). It fixes Windows 11 reboots when
> > > GWDT is present (without WDAT). With that fixed it's up to MS to fix
> > > their driver to set sane timeout as with the current one wdatchdog
> > > will never trigger.
> >
> > given merge window should be open by now,
> > gentle ping
>
> 2 weeks later,
> yet another ping
>
> >
> > > Windows doesn't ship built-in TCO watchdog driver, and users are
> > > forced to install vendor specific driver(s) if such exists.
> > > However the OS provides a generic watchdog driver that uses
> > > ACPI WDAT table [1] to abstract actual hardware behind it.
> > > The same applies to ARM version of Windows.
> > >
> > > This series adds
> > > * WDAT table tailored for TCO watchdog that Q35 already
> > > has as part of ICH9 chipset and a knob to enable it.
> > > * SBSA GWDT to arm/virt machine with WDAT table tailored
> > > for it and necessary tweaks to GWDT to make usable
> > > with WDAT driver.
> > > * in addition to WDAT, it also adds native variant
> > > with GWDT described in FDT and DTDT
> > > (broken on Windows/works on linux).
> > >
> > > Guest OS WDAT support is present since Windows Vista and Linux since 2016[2].
> > >
> > > One can test it launching VM with following options:
> > > * x86:
> > > -machine q35,wdat=on
> > > * arm/virt:
> > > -device sbsa_gwdt,wdat=on
> > >
> > > to trace access to TCO registers one can add to CLI:
> > > -trace "tco_*"
> > > to trace access to GWDT registers one can add to CLI:
> > > -trace "sbsa_gwdt*"
> > >
> > > To verify that guest uses WDAT (both Windows and Linux would use it if present),
> > > * on linux make sure that watchdog service is configured/enabled
> > > (use wdctl to check what watchdog device is in use) and then
> > > trigger kernel panic with command:
> > > echo c > /proc/sysrq-trigger
> > > * on Windows kill svchost process, running cmd in admin mode:
> > > taskkill /f /im svchost.exe
> > >
> > > Tested with WS2025 & RHEL9.6 & Fedora 43 (aarch64)
> > >
> > > git tree at: https://gitlab.com/imammedo/qemu/-/commits/gwdt_v2
> > >
> > > 1) http://msdn.microsoft.com/en-us/windows/hardware/gg463320.aspx
> > > 2) https://lwn.net/Articles/700524/
> > >
> > > PS:
> > > previous revision:
> > > https://patchew.org/QEMU/20260206131438.1857182-1-imammedo@redhat.com/
> > >
> > > Igor Mammedov (21):
> > > acpi: add API to build WDAT instructions
> > > x86: q35: add 'wdat' property
> > > x86: q35: generate WDAT ACPI table
> > > tests: acpi: x86/q35: whitelist new WDAT table
> > > tests: acpi: x86/q35: add WDAT table test case
> > > tests: acpi: x86/q35: update expected WDAT blob
> > > arm: sbsa_gwdt: fixup default "clock-frequency"
> > > arm: add tracing events to sbsa_gwdt
> > > arm: virt: create sbsa_gwdt watchdog
> > > arm: sbsa_gwdt: add 'wdat' option
> > > arm: virt: add support for WDAT based watchdog
> > > tests: acpi: arm/virt: whitelist new WDAT table
> > > tests: acpi: arm/virt: add WDAT table test case
> > > tests: acpi: arm/virt: update expected WDAT blob
> > > tests: acpi: arm/virt: whitelist GTDT table
> > > tests: acpi: arm/virt: add GTDT watchdog table test case
> > > tests: acpi: arm/virt: update expected GTDT blob
> > > sbsa_gwdt: reduce code ident
> > > sbsa_gwdt: move all foo_REFRESH logic under REFRESH condition
> > > sbsa_gwdt: reschedule timer on direct WCV load
> > > sbsa_gwdt: limit compare_value to INT64_MAX
> > >
> > > include/hw/acpi/wdat-gwdt.h | 19 ++++
> > > include/hw/acpi/wdat-ich9.h | 15 ++++
> > > include/hw/acpi/wdat.h | 118 +++++++++++++++++++++++++
> > > include/hw/i386/pc.h | 1 +
> > > include/hw/watchdog/sbsa_gwdt.h | 1 +
> > > hw/acpi/aml-build.c | 14 +++
> > > hw/acpi/meson.build | 5 +-
> > > hw/acpi/wdat-gwdt-stub.c | 16 ++++
> > > hw/acpi/wdat-gwdt.c | 92 +++++++++++++++++++
> > > hw/acpi/wdat-ich9-stub.c | 15 ++++
> > > hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++
> > > hw/arm/Kconfig | 1 +
> > > hw/arm/virt-acpi-build.c | 65 +++++++++++++-
> > > hw/arm/virt.c | 2 +
> > > hw/core/sysbus-fdt.c | 32 +++++++
> > > hw/i386/acpi-build.c | 12 +++
> > > hw/i386/pc_q35.c | 18 ++++
> > > hw/watchdog/sbsa_gwdt.c | 65 +++++++++-----
> > > hw/watchdog/trace-events | 9 ++
> > > tests/data/acpi/aarch64/virt/GTDT.gwdt | Bin 0 -> 132 bytes
> > > tests/data/acpi/aarch64/virt/WDAT.wdat | Bin 0 -> 260 bytes
> > > tests/data/acpi/x86/q35/WDAT.wdat | Bin 0 -> 308 bytes
> > > tests/qtest/bios-tables-test.c | 54 +++++++++++
> > > 23 files changed, 618 insertions(+), 26 deletions(-)
> > > create mode 100644 include/hw/acpi/wdat-gwdt.h
> > > create mode 100644 include/hw/acpi/wdat-ich9.h
> > > create mode 100644 include/hw/acpi/wdat.h
> > > create mode 100644 hw/acpi/wdat-gwdt-stub.c
> > > create mode 100644 hw/acpi/wdat-gwdt.c
> > > create mode 100644 hw/acpi/wdat-ich9-stub.c
> > > create mode 100644 hw/acpi/wdat-ich9.c
> > > create mode 100644 tests/data/acpi/aarch64/virt/GTDT.gwdt
> > > create mode 100644 tests/data/acpi/aarch64/virt/WDAT.wdat
> > > create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
> > >
> >
>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards
2026-03-03 9:25 [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
` (21 preceding siblings ...)
2026-04-28 14:12 ` [PATCH v2 00/21] Introduce ACPI watchdog for Q35 and arm/virt boards Igor Mammedov
@ 2026-06-03 6:17 ` Michael S. Tsirkin
22 siblings, 0 replies; 57+ messages in thread
From: Michael S. Tsirkin @ 2026-06-03 6:17 UTC (permalink / raw)
To: Igor Mammedov
Cc: qemu-devel, anisinha, pbonzini, peter.maydell, shannon.zhaosl,
philmd, zhao1.liu, rad, leif.lindholm, qemu-arm
On Tue, Mar 03, 2026 at 10:25:11AM +0100, Igor Mammedov wrote:
> Changelog:
> v2:
> * ditch generic '-machine acpi-watchdog' option in favor of
> board specific variants:
> x86/q35: -machine wdat={on|off}
> arm/virt: -device sbsa_gwdt,wdat={on|off}
> * arm/virt: add FDT and GTDT ACPI entries for GWDT when it's present
> and hide GDTD one when WDAT is enabled.
> * arm/virt: add test case for GTDT
> * [18-21] optional GWDT cleanup/fixes in handling WCV register update,
> make QEMU behave according to spec (at least the way I read it and
> it appears MS also read it that way). It fixes Windows 11 reboots when
> GWDT is present (without WDAT). With that fixed it's up to MS to fix
> their driver to set sane timeout as with the current one wdatchdog
> will never trigger.
I picked the x86 patches for now.
> Windows doesn't ship built-in TCO watchdog driver, and users are
> forced to install vendor specific driver(s) if such exists.
> However the OS provides a generic watchdog driver that uses
> ACPI WDAT table [1] to abstract actual hardware behind it.
> The same applies to ARM version of Windows.
>
> This series adds
> * WDAT table tailored for TCO watchdog that Q35 already
> has as part of ICH9 chipset and a knob to enable it.
> * SBSA GWDT to arm/virt machine with WDAT table tailored
> for it and necessary tweaks to GWDT to make usable
> with WDAT driver.
> * in addition to WDAT, it also adds native variant
> with GWDT described in FDT and DTDT
> (broken on Windows/works on linux).
>
> Guest OS WDAT support is present since Windows Vista and Linux since 2016[2].
>
> One can test it launching VM with following options:
> * x86:
> -machine q35,wdat=on
> * arm/virt:
> -device sbsa_gwdt,wdat=on
>
> to trace access to TCO registers one can add to CLI:
> -trace "tco_*"
> to trace access to GWDT registers one can add to CLI:
> -trace "sbsa_gwdt*"
>
> To verify that guest uses WDAT (both Windows and Linux would use it if present),
> * on linux make sure that watchdog service is configured/enabled
> (use wdctl to check what watchdog device is in use) and then
> trigger kernel panic with command:
> echo c > /proc/sysrq-trigger
> * on Windows kill svchost process, running cmd in admin mode:
> taskkill /f /im svchost.exe
>
> Tested with WS2025 & RHEL9.6 & Fedora 43 (aarch64)
>
> git tree at: https://gitlab.com/imammedo/qemu/-/commits/gwdt_v2
>
> 1) http://msdn.microsoft.com/en-us/windows/hardware/gg463320.aspx
> 2) https://lwn.net/Articles/700524/
>
> PS:
> previous revision:
> https://patchew.org/QEMU/20260206131438.1857182-1-imammedo@redhat.com/
>
> Igor Mammedov (21):
> acpi: add API to build WDAT instructions
> x86: q35: add 'wdat' property
> x86: q35: generate WDAT ACPI table
> tests: acpi: x86/q35: whitelist new WDAT table
> tests: acpi: x86/q35: add WDAT table test case
> tests: acpi: x86/q35: update expected WDAT blob
> arm: sbsa_gwdt: fixup default "clock-frequency"
> arm: add tracing events to sbsa_gwdt
> arm: virt: create sbsa_gwdt watchdog
> arm: sbsa_gwdt: add 'wdat' option
> arm: virt: add support for WDAT based watchdog
> tests: acpi: arm/virt: whitelist new WDAT table
> tests: acpi: arm/virt: add WDAT table test case
> tests: acpi: arm/virt: update expected WDAT blob
> tests: acpi: arm/virt: whitelist GTDT table
> tests: acpi: arm/virt: add GTDT watchdog table test case
> tests: acpi: arm/virt: update expected GTDT blob
> sbsa_gwdt: reduce code ident
> sbsa_gwdt: move all foo_REFRESH logic under REFRESH condition
> sbsa_gwdt: reschedule timer on direct WCV load
> sbsa_gwdt: limit compare_value to INT64_MAX
>
> include/hw/acpi/wdat-gwdt.h | 19 ++++
> include/hw/acpi/wdat-ich9.h | 15 ++++
> include/hw/acpi/wdat.h | 118 +++++++++++++++++++++++++
> include/hw/i386/pc.h | 1 +
> include/hw/watchdog/sbsa_gwdt.h | 1 +
> hw/acpi/aml-build.c | 14 +++
> hw/acpi/meson.build | 5 +-
> hw/acpi/wdat-gwdt-stub.c | 16 ++++
> hw/acpi/wdat-gwdt.c | 92 +++++++++++++++++++
> hw/acpi/wdat-ich9-stub.c | 15 ++++
> hw/acpi/wdat-ich9.c | 90 +++++++++++++++++++
> hw/arm/Kconfig | 1 +
> hw/arm/virt-acpi-build.c | 65 +++++++++++++-
> hw/arm/virt.c | 2 +
> hw/core/sysbus-fdt.c | 32 +++++++
> hw/i386/acpi-build.c | 12 +++
> hw/i386/pc_q35.c | 18 ++++
> hw/watchdog/sbsa_gwdt.c | 65 +++++++++-----
> hw/watchdog/trace-events | 9 ++
> tests/data/acpi/aarch64/virt/GTDT.gwdt | Bin 0 -> 132 bytes
> tests/data/acpi/aarch64/virt/WDAT.wdat | Bin 0 -> 260 bytes
> tests/data/acpi/x86/q35/WDAT.wdat | Bin 0 -> 308 bytes
> tests/qtest/bios-tables-test.c | 54 +++++++++++
> 23 files changed, 618 insertions(+), 26 deletions(-)
> create mode 100644 include/hw/acpi/wdat-gwdt.h
> create mode 100644 include/hw/acpi/wdat-ich9.h
> create mode 100644 include/hw/acpi/wdat.h
> create mode 100644 hw/acpi/wdat-gwdt-stub.c
> create mode 100644 hw/acpi/wdat-gwdt.c
> create mode 100644 hw/acpi/wdat-ich9-stub.c
> create mode 100644 hw/acpi/wdat-ich9.c
> create mode 100644 tests/data/acpi/aarch64/virt/GTDT.gwdt
> create mode 100644 tests/data/acpi/aarch64/virt/WDAT.wdat
> create mode 100644 tests/data/acpi/x86/q35/WDAT.wdat
>
> --
> 2.47.3
^ permalink raw reply [flat|nested] 57+ messages in thread