Re: [PATCH v3 1/2] power: reset: Add QEMU virt-ctrl driver

Sebastian Reichel <[email protected]>
Newsgroups org.kernel.vger.linux-m68k,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pm
Message-ID <ac7kP64nbhZzwbJV@venus>
Hi,

On Sun, Feb 22, 2026 at 05:32:24PM +0000, Kuan-Wei Chiu wrote:
> Add a new driver for the 'virt-ctrl' device found on QEMU virt machines
> (e.g. m68k). This device provides a simple interface for system reset
> and power off [1].
> 
> This driver utilizes the modern system-off API to register callbacks
> for both system restart and power off. It also registers a reboot
> notifier to catch SYS_HALT events, ensuring that LINUX_REBOOT_CMD_HALT
> is properly handled. It is designed to be generic and can be reused by
> other architectures utilizing this QEMU device.
> 
> Link: https://gitlab.com/qemu-project/qemu/-/blob/v10.2.0/hw/misc/virt_ctrl.c [1]
> Signed-off-by: Kuan-Wei Chiu <[email protected]>
> ---

I think this should be merged with the second patch via the m68k
tree:

Acked-by: Sebastian Reichel <[email protected]>

Greetings,

-- Sebastian

> Changes in v3:
> - Add a reboot notifier to handle SYS_HALT.
> - Implement virt_ctrl_write32() to handle native endianness.
> 
> I noticed devm_register_sys_off_handler() currently lacks a
> SYS_OFF_MODE_HALT. Therefore, I registered a standard reboot notifier
> for SYS_HALT, while keeping restart and power-off on the sys-off API.
> 
>  MAINTAINERS                          |   6 ++
>  drivers/power/reset/Kconfig          |  10 +++
>  drivers/power/reset/Makefile         |   1 +
>  drivers/power/reset/qemu-virt-ctrl.c | 122 +++++++++++++++++++++++++++
>  4 files changed, 139 insertions(+)
>  create mode 100644 drivers/power/reset/qemu-virt-ctrl.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 55af015174a5..aa9eb8540637 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -21441,6 +21441,12 @@ S:	Maintained
>  F:	drivers/firmware/qemu_fw_cfg.c
>  F:	include/uapi/linux/qemu_fw_cfg.h
>  
> +QEMU VIRT MACHINE SYSTEM CONTROLLER DRIVER
> +M:	Kuan-Wei Chiu <[email protected]>
> +L:	[email protected]
> +S:	Maintained
> +F:	drivers/power/reset/qemu-virt-ctrl.c
> +
>  QLOGIC QL41xxx FCOE DRIVER
>  M:	Saurav Kashyap <[email protected]>
>  M:	Javed Hasan <[email protected]>
> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> index f6c1bcbb57de..99e3334726a5 100644
> --- a/drivers/power/reset/Kconfig
> +++ b/drivers/power/reset/Kconfig
> @@ -354,4 +354,14 @@ config POWER_MLXBF
>  	help
>  	  This driver supports reset or low power mode handling for Mellanox BlueField.
>  
> +config POWER_RESET_QEMU_VIRT_CTRL
> +	tristate "QEMU Virt Machine System Controller"
> +	depends on HAS_IOMEM
> +	help
> +	  This driver supports the system reset and power off functionality
> +	  provided by the QEMU 'virt-ctrl' device.
> +
> +	  Say Y here if you are running Linux on a QEMU virtual machine that
> +	  provides this controller, such as the m68k virt machine.
> +
>  endif
> diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
> index 0e4ae6f6b5c5..d7ae97241a83 100644
> --- a/drivers/power/reset/Makefile
> +++ b/drivers/power/reset/Makefile
> @@ -41,3 +41,4 @@ obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
>  obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
>  obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
>  obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o
> +obj-$(CONFIG_POWER_RESET_QEMU_VIRT_CTRL) += qemu-virt-ctrl.o
> diff --git a/drivers/power/reset/qemu-virt-ctrl.c b/drivers/power/reset/qemu-virt-ctrl.c
> new file mode 100644
> index 000000000000..f40d04afd4e3
> --- /dev/null
> +++ b/drivers/power/reset/qemu-virt-ctrl.c
> @@ -0,0 +1,122 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * QEMU Virt Machine System Controller Driver
> + *
> + * Copyright (C) 2026 Kuan-Wei Chiu <[email protected]>
> + */
> +
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/platform_device.h>
> +#include <linux/reboot.h>
> +
> +/* Registers */
> +#define VIRT_CTRL_REG_FEATURES	0x00
> +#define VIRT_CTRL_REG_CMD	0x04
> +
> +/* Commands */
> +#define CMD_NOOP	0
> +#define CMD_RESET	1
> +#define CMD_HALT	2
> +#define CMD_PANIC	3
> +
> +struct qemu_virt_ctrl {
> +	void __iomem *base;
> +	struct notifier_block reboot_nb;
> +};
> +
> +static inline void virt_ctrl_write32(u32 val, void __iomem *addr)
> +{
> +	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
> +		iowrite32be(val, addr);
> +	else
> +		iowrite32(val, addr);
> +}
> +
> +static int qemu_virt_ctrl_power_off(struct sys_off_data *data)
> +{
> +	void __iomem *base = data->cb_data;
> +
> +	virt_ctrl_write32(CMD_HALT, base + VIRT_CTRL_REG_CMD);
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static int qemu_virt_ctrl_restart(struct sys_off_data *data)
> +{
> +	void __iomem *base = data->cb_data;
> +
> +	virt_ctrl_write32(CMD_RESET, base + VIRT_CTRL_REG_CMD);
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static int qemu_virt_ctrl_reboot_notify(struct notifier_block *nb,
> +					unsigned long action, void *data)
> +{
> +	struct qemu_virt_ctrl *ctrl = container_of(nb, struct qemu_virt_ctrl, reboot_nb);
> +
> +	if (action == SYS_HALT)
> +		virt_ctrl_write32(CMD_HALT, ctrl->base + VIRT_CTRL_REG_CMD);
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static int qemu_virt_ctrl_probe(struct platform_device *pdev)
> +{
> +	struct qemu_virt_ctrl *ctrl;
> +	int ret;
> +
> +	ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
> +	if (!ctrl)
> +		return -ENOMEM;
> +
> +	ctrl->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(ctrl->base))
> +		return PTR_ERR(ctrl->base);
> +
> +	ret = devm_register_sys_off_handler(&pdev->dev,
> +					    SYS_OFF_MODE_RESTART,
> +					    SYS_OFF_PRIO_DEFAULT,
> +					    qemu_virt_ctrl_restart,
> +					    ctrl->base);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "cannot register restart handler\n");
> +
> +	ret = devm_register_sys_off_handler(&pdev->dev,
> +					    SYS_OFF_MODE_POWER_OFF,
> +					    SYS_OFF_PRIO_DEFAULT,
> +					    qemu_virt_ctrl_power_off,
> +					    ctrl->base);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "cannot register power-off handler\n");
> +
> +	ctrl->reboot_nb.notifier_call = qemu_virt_ctrl_reboot_notify;
> +	ret = devm_register_reboot_notifier(&pdev->dev, &ctrl->reboot_nb);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret, "cannot register reboot notifier\n");
> +
> +	return 0;
> +}
> +
> +static const struct platform_device_id qemu_virt_ctrl_id[] = {
> +	{ "qemu-virt-ctrl", 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(platform, qemu_virt_ctrl_id);
> +
> +static struct platform_driver qemu_virt_ctrl_driver = {
> +	.probe = qemu_virt_ctrl_probe,
> +	.driver = {
> +		.name = "qemu-virt-ctrl",
> +	},
> +	.id_table = qemu_virt_ctrl_id,
> +};
> +module_platform_driver(qemu_virt_ctrl_driver);
> +
> +MODULE_AUTHOR("Kuan-Wei Chiu <[email protected]>");
> +MODULE_DESCRIPTION("QEMU Virt Machine System Controller Driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.53.0.345.g96ddfc5eaa-goog
>
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEE72YNB0Y/i3JqeVQT2O7X88g7+poFAmnO5QcACgkQ2O7X88g7
+pq62xAAgx6BpLHcu/yz35xgJEamyr/x9F/FpYwJ8ZrrGT6w5zFfbBB6OU9Nbq5R
NKObno/58BHIJ2rqCNe+GcaXkMWXDufxGcOgjB15Inu3DGN4mbt6X65shHToQg9q
1rSVD9NEMg9RcGXyDkbHw2rlPzohQIL3IDJsUwb+ncKyNW+tu7ZXKHPMiKdR8l3G
Wcn+2DxEQS3ZN/1JjfRt3fl2W5t2JcddvLWShzdxNqlygRjUyJkT+jpDNAVO/0Tm
BpBCiL15VDFXWcHxuUTCMOS0o5+JY038w0l+Fvaj8gnZ+zOuJDrFCWOrRv2JeVA2
Wr0hHy86xBdNyj+MI63fUeAS1ShUWH4baRF+xSjwwG9HYGFDxjP6WM6fO6VxXOqm
mew/LWvj6UtQhNmfHfw3LyOOkjsv31ifRqQkX8o+pIwiFj6FwZbaY+szpNOPhLA7
nb+Lg5+362F6iXW2akco+W370HK1I4OKd/c+eG22j+Tg6BtSaqZNP4U3+AEb3CKP
6tbnNw9aev5rPUmsVZBAKOq2EL8kinO/8I/R6BYOXpWRRrtzGXHzlNcGiWCxXW19
bTTvS6dIzwvlwO2vaTwO6sBix8KG1Svsla8CKZQUW11UfoVN6YaDJLFzdsY213B1
CEhcQ+b+7KScnZZ9TH40RKk7qipemmtJ/z7Ua0SLx9k+dpviric=
=nTBP
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.