Module Name:    src
Committed By:   riastradh
Date:           Mon Aug 26 13:38:29 UTC 2024

Modified Files:
        src/distrib/sets/lists/man: mi
        src/distrib/sets/lists/manhtml: mi
        src/distrib/sets/lists/modules: md.amd64 md.i386
        src/share/man/man4: Makefile
        src/sys/arch/amd64/conf: ALL
        src/sys/arch/i386/conf: ALL
        src/sys/dev/acpi: files.acpi
        src/sys/modules: Makefile
Added Files:
        src/share/man/man4: acpivmgenid.4
        src/sys/dev/acpi: acpi_vmgenid.c
        src/sys/modules/acpivmgenid: Makefile acpivmgenid.ioconf

Log Message:
acpivmgenid(4): New driver for virtual machine generation ID.

Added to amd64/ALL and i386/ALL kernel configurations, and made
available as a loadable module acpivmgenid.kmod on x86, for now.

TBD: Add to all ACPI-supporting GENERIC kernels.

PR kern/58632: getentropy(2) and arc4random(3) do not reseed on VM
fork


To generate a diff of this commit:
cvs rdiff -u -r1.1785 -r1.1786 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.7 -r1.8 src/distrib/sets/lists/manhtml/mi
cvs rdiff -u -r1.102 -r1.103 src/distrib/sets/lists/modules/md.amd64
cvs rdiff -u -r1.99 -r1.100 src/distrib/sets/lists/modules/md.i386
cvs rdiff -u -r1.734 -r1.735 src/share/man/man4/Makefile
cvs rdiff -u -r0 -r1.1 src/share/man/man4/acpivmgenid.4
cvs rdiff -u -r1.189 -r1.190 src/sys/arch/amd64/conf/ALL
cvs rdiff -u -r1.520 -r1.521 src/sys/arch/i386/conf/ALL
cvs rdiff -u -r0 -r1.1 src/sys/dev/acpi/acpi_vmgenid.c
cvs rdiff -u -r1.132 -r1.133 src/sys/dev/acpi/files.acpi
cvs rdiff -u -r1.291 -r1.292 src/sys/modules/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/modules/acpivmgenid/Makefile \
    src/sys/modules/acpivmgenid/acpivmgenid.ioconf

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1785 src/distrib/sets/lists/man/mi:1.1786
--- src/distrib/sets/lists/man/mi:1.1785	Mon Aug 19 15:04:05 2024
+++ src/distrib/sets/lists/man/mi	Mon Aug 26 13:38:27 2024
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1785 2024/08/19 15:04:05 riastradh Exp $
+# $NetBSD: mi,v 1.1786 2024/08/26 13:38:27 riastradh Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.man				man-sys-root
@@ -834,6 +834,7 @@
 ./usr/share/man/cat4/acpismbus.0		man-sys-catman		.cat
 ./usr/share/man/cat4/acpitz.0			man-sys-catman		.cat
 ./usr/share/man/cat4/acpivga.0			man-sys-catman		.cat
+./usr/share/man/cat4/acpivmgenid.0		man-sys-catman		.cat
 ./usr/share/man/cat4/acpiwdrt.0			man-sys-catman		.cat
 ./usr/share/man/cat4/acpiwmi.0			man-sys-catman		.cat
 ./usr/share/man/cat4/adb.0			man-sys-catman		.cat
@@ -4391,6 +4392,7 @@
 ./usr/share/man/man4/acpismbus.4		man-sys-man		.man
 ./usr/share/man/man4/acpitz.4			man-sys-man		.man
 ./usr/share/man/man4/acpivga.4			man-sys-man		.man
+./usr/share/man/man4/acpivmgenid.4		man-sys-man		.man
 ./usr/share/man/man4/acpiwdrt.4			man-sys-man		.man
 ./usr/share/man/man4/acpiwmi.4			man-sys-man		.man
 ./usr/share/man/man4/adb.4			man-sys-man		.man

Index: src/distrib/sets/lists/manhtml/mi
diff -u src/distrib/sets/lists/manhtml/mi:1.7 src/distrib/sets/lists/manhtml/mi:1.8
--- src/distrib/sets/lists/manhtml/mi:1.7	Mon Aug 19 15:04:05 2024
+++ src/distrib/sets/lists/manhtml/mi	Mon Aug 26 13:38:28 2024
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.7 2024/08/19 15:04:05 riastradh Exp $
+# $NetBSD: mi,v 1.8 2024/08/26 13:38:28 riastradh Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -755,6 +755,7 @@
 ./usr/share/man/html4/acpismbus.html		man-sys-htmlman		html
 ./usr/share/man/html4/acpitz.html		man-sys-htmlman		html
 ./usr/share/man/html4/acpivga.html		man-sys-htmlman		html
+./usr/share/man/html4/acpivmgenid.html		man-sys-htmlman		html
 ./usr/share/man/html4/acpiwdrt.html		man-sys-htmlman		html
 ./usr/share/man/html4/acpiwmi.html		man-sys-htmlman		html
 ./usr/share/man/html4/adb.html			man-sys-htmlman		html

Index: src/distrib/sets/lists/modules/md.amd64
diff -u src/distrib/sets/lists/modules/md.amd64:1.102 src/distrib/sets/lists/modules/md.amd64:1.103
--- src/distrib/sets/lists/modules/md.amd64:1.102	Thu Mar 21 02:36:01 2024
+++ src/distrib/sets/lists/modules/md.amd64	Mon Aug 26 13:38:28 2024
@@ -1,4 +1,4 @@
-# $NetBSD: md.amd64,v 1.102 2024/03/21 02:36:01 riastradh Exp $
+# $NetBSD: md.amd64,v 1.103 2024/08/26 13:38:28 riastradh Exp $
 #
 ./@MODULEDIR@/acpiacad				modules-base-kernel	kmod
 ./@MODULEDIR@/acpiacad/acpiacad.kmod		modules-base-kernel	kmod
@@ -24,6 +24,8 @@
 ./@MODULEDIR@/acpiverbose/acpiverbose.kmod	modules-base-kernel	kmod
 ./@MODULEDIR@/acpivga				modules-base-kernel	kmod
 ./@MODULEDIR@/acpivga/acpivga.kmod		modules-base-kernel	kmod
+./@MODULEDIR@/acpivmgenid			modules-base-kernel	kmod
+./@MODULEDIR@/acpivmgenid/acpivmgenid.kmod	modules-base-kernel	kmod
 ./@MODULEDIR@/acpiwdrt				modules-base-kernel	kmod
 ./@MODULEDIR@/acpiwdrt/acpiwdrt.kmod		modules-base-kernel	kmod
 ./@MODULEDIR@/acpiwmi				modules-base-kernel	kmod

Index: src/distrib/sets/lists/modules/md.i386
diff -u src/distrib/sets/lists/modules/md.i386:1.99 src/distrib/sets/lists/modules/md.i386:1.100
--- src/distrib/sets/lists/modules/md.i386:1.99	Thu Mar 21 02:36:01 2024
+++ src/distrib/sets/lists/modules/md.i386	Mon Aug 26 13:38:28 2024
@@ -1,4 +1,4 @@
-# $NetBSD: md.i386,v 1.99 2024/03/21 02:36:01 riastradh Exp $
+# $NetBSD: md.i386,v 1.100 2024/08/26 13:38:28 riastradh Exp $
 #
 ./@MODULEDIR@/acpiacad				modules-base-kernel	kmod
 ./@MODULEDIR@/acpiacad/acpiacad.kmod		modules-base-kernel	kmod
@@ -24,6 +24,8 @@
 ./@MODULEDIR@/acpiverbose/acpiverbose.kmod	modules-base-kernel	kmod
 ./@MODULEDIR@/acpivga				modules-base-kernel	kmod
 ./@MODULEDIR@/acpivga/acpivga.kmod		modules-base-kernel	kmod
+./@MODULEDIR@/acpivmgenid			modules-base-kernel	kmod
+./@MODULEDIR@/acpivmgenid/acpivmgenid.kmod	modules-base-kernel	kmod
 ./@MODULEDIR@/acpiwdrt				modules-base-kernel	kmod
 ./@MODULEDIR@/acpiwdrt/acpiwdrt.kmod		modules-base-kernel	kmod
 ./@MODULEDIR@/acpiwmi				modules-base-kernel	kmod

Index: src/share/man/man4/Makefile
diff -u src/share/man/man4/Makefile:1.734 src/share/man/man4/Makefile:1.735
--- src/share/man/man4/Makefile:1.734	Mon Aug 19 15:04:05 2024
+++ src/share/man/man4/Makefile	Mon Aug 26 13:38:28 2024
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.734 2024/08/19 15:04:05 riastradh Exp $
+#	$NetBSD: Makefile,v 1.735 2024/08/26 13:38:28 riastradh Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/18/93
 
 MAN=	aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
@@ -100,7 +100,8 @@ MAN+=	irframe.4 cir.4 irframetty.4 oboe.
 # ACPI devices
 MAN+=	acpi.4 acpiacad.4 acpibat.4 acpibut.4 acpicpu.4 \
 	acpidalb.4 acpiec.4 acpifan.4 acpihed.4 acpilid.4 \
-	acpipmtr.4 acpismbus.4 acpitz.4 acpivga.4 acpiwdrt.4 acpiwmi.4
+	acpipmtr.4 acpismbus.4 acpitz.4 acpivga.4 acpivmgenid.4 \
+	acpiwdrt.4 acpiwmi.4
 MAN+=	apei.4
 
 # Radio devices

Index: src/sys/arch/amd64/conf/ALL
diff -u src/sys/arch/amd64/conf/ALL:1.189 src/sys/arch/amd64/conf/ALL:1.190
--- src/sys/arch/amd64/conf/ALL:1.189	Tue Jul 16 12:01:18 2024
+++ src/sys/arch/amd64/conf/ALL	Mon Aug 26 13:38:28 2024
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.189 2024/07/16 12:01:18 riastradh Exp $
+# $NetBSD: ALL,v 1.190 2024/08/26 13:38:28 riastradh Exp $
 # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
 #
 # ALL machine description file
@@ -17,7 +17,7 @@ include 	"arch/amd64/conf/std.amd64"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"ALL-$Revision: 1.189 $"
+#ident		"ALL-$Revision: 1.190 $"
 
 maxusers	64		# estimated number of users
 
@@ -381,6 +381,7 @@ acpismbus*	at acpi?		# ACPI SMBus CMI (e
 acpitz* 	at acpi?		# ACPI Thermal Zone
 acpivga*	at acpi?		# ACPI Display Adapter
 acpiout*	at acpivga?		# ACPI Display Output Device
+acpivmgenid*	at acpi?		# ACPI Virtual Machine Generation ID
 acpiwdrt*	at acpi?		# ACPI Watchdog Resource Table
 acpiwmi*	at acpi?		# ACPI WMI Mapper
 apei*		at apeibus?		# ACPI Platform Error Interfaces

Index: src/sys/arch/i386/conf/ALL
diff -u src/sys/arch/i386/conf/ALL:1.520 src/sys/arch/i386/conf/ALL:1.521
--- src/sys/arch/i386/conf/ALL:1.520	Tue Jul 16 12:01:19 2024
+++ src/sys/arch/i386/conf/ALL	Mon Aug 26 13:38:28 2024
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.520 2024/07/16 12:01:19 riastradh Exp $
+# $NetBSD: ALL,v 1.521 2024/08/26 13:38:28 riastradh Exp $
 # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
 #
 # ALL machine description file
@@ -17,7 +17,7 @@ include 	"arch/i386/conf/std.i386"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"ALL-$Revision: 1.520 $"
+#ident		"ALL-$Revision: 1.521 $"
 
 maxusers	64		# estimated number of users
 
@@ -368,6 +368,7 @@ acpismbus*	at acpi?		# ACPI SMBus CMI (e
 acpitz* 	at acpi?		# ACPI Thermal Zone
 acpivga*	at acpi?		# ACPI Display Adapter
 acpiout*	at acpivga?		# ACPI Display Output Device
+acpivmgenid*	at acpi?		# ACPI Virtual Machine Generation ID
 acpiwdrt*	at acpi?		# ACPI Watchdog Resource Table
 acpiwmi*	at acpi?		# ACPI WMI Mapper
 apei*		at apeibus?		# ACPI Platform Error Interfaces

Index: src/sys/dev/acpi/files.acpi
diff -u src/sys/dev/acpi/files.acpi:1.132 src/sys/dev/acpi/files.acpi:1.133
--- src/sys/dev/acpi/files.acpi:1.132	Thu Mar 21 02:36:01 2024
+++ src/sys/dev/acpi/files.acpi	Mon Aug 26 13:38:28 2024
@@ -1,4 +1,4 @@
-#	$NetBSD: files.acpi,v 1.132 2024/03/21 02:36:01 riastradh Exp $
+#	$NetBSD: files.acpi,v 1.133 2024/08/26 13:38:28 riastradh Exp $
 
 defflag	opt_acpi.h	ACPIVERBOSE ACPI_DEBUG ACPI_ACTIVATE_DEV
 			ACPI_DSDT_OVERRIDE ACPI_SCANPCI ACPI_BREAKPOINT
@@ -116,6 +116,11 @@ device	acpicppc: acpipcc
 attach	acpicppc at acpinodebus
 file	dev/acpi/acpi_cppc.c		acpicppc
 
+# ACPI Virtual Machine Generation ID
+device	acpivmgenid
+attach	acpivmgenid at acpinodebus
+file	dev/acpi/acpi_vmgenid.c		acpivmgenid
+
 # ACPI Platform Error Interface
 device	apei
 attach	apei at apeibus

Index: src/sys/modules/Makefile
diff -u src/sys/modules/Makefile:1.291 src/sys/modules/Makefile:1.292
--- src/sys/modules/Makefile:1.291	Thu Jul 18 04:28:55 2024
+++ src/sys/modules/Makefile	Mon Aug 26 13:38:28 2024
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.291 2024/07/18 04:28:55 rin Exp $
+#	$NetBSD: Makefile,v 1.292 2024/08/26 13:38:28 riastradh Exp $
 
 .include <bsd.own.mk>
 
@@ -298,6 +298,7 @@ SUBDIR+=	acpilid
 SUBDIR+=	acpipmtr
 SUBDIR+=	acpitz
 SUBDIR+=	acpivga
+SUBDIR+=	acpivmgenid
 SUBDIR+=	acpiwdrt
 SUBDIR+=	acpiwmi
 SUBDIR+=	aibs

Added files:

Index: src/share/man/man4/acpivmgenid.4
diff -u /dev/null src/share/man/man4/acpivmgenid.4:1.1
--- /dev/null	Mon Aug 26 13:38:29 2024
+++ src/share/man/man4/acpivmgenid.4	Mon Aug 26 13:38:28 2024
@@ -0,0 +1,112 @@
+.\"	$NetBSD: acpivmgenid.4,v 1.1 2024/08/26 13:38:28 riastradh Exp $
+.\"
+.\" Copyright (c) 2024 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd August 25, 2024
+.Dt ACPIVMGENID 4
+.Os
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh NAME
+.Nm acpivmgenid
+.Nd ACPI Virtual Machine Generation ID
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh SYNOPSIS
+.Cd "acpivmgenid* at acpi?"
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh DESCRIPTION
+.Nm
+provides a generation ID for virtual machines.
+.Pp
+When starting two otherwise identical virtual machines, whether from
+the same clean image or by cloning snapshots or any other mechanism,
+the VM host may choose a different generation ID.
+Although this generation ID is not secret, it is incorporated into the
+.Xr entropy 7
+pool (with a measure of zero entropy) so that the two virtual machines
+will produce independent random output.
+.Pp
+If a live VM is cloned, the VM host may change the generation ID in one
+or both of the clones and notify them through the
+.Nm
+device.
+When this happens,
+.Nx
+will reseed system random number generators, so that output of
+.Pa /dev/urandom
+and
+.Xr getentropy 3
+will be independent in the two clones.
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh SYSCTLS
+The following
+.Xr sysctl 7
+nodes are available:
+.Bl -tag -width Li
+.It Li "hw.acpivmgenid" Ns Va N Ns Li ".id"
+The current 16-byte VM generation ID.
+.It Li "hw.acpivmgenid" Ns Va N Ns Li ".paddr"
+The physical address of the VM generation ID provided by the host.
+.El
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh SEE ALSO
+.Xr arc4random 3 ,
+.Xr getentropy 3 ,
+.Xr rnd 4 ,
+.Xr entropy 7
+.Rs
+.%T Virtual Machine Generation ID
+.%Q Microsoft
+.%D 2018-08-01
+.%U http://go.microsoft.com/fwlink/?LinkId=260709
+.Re
+.Rs
+.%T Virtual Machine Generation ID Device
+.%Q The QEMU Project Developers
+.%U https://www.qemu.org/docs/master/specs/vmgenid.html
+.Re
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Nx 11.0 .
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh BUGS
+Currently
+.Nx
+does not request fresh samples from all on-demand entropy sources when
+the VM generation ID changes, so although the outputs of the system
+entropy pool appear independent to an outside observer, disclosing the
+kernel memory of one VM clone to an adversary may allow the adversary
+to predict another VM clone's
+.Pa /dev/urandom
+outputs.
+.Pp
+Currently
+.Xr arc4random 3
+is not reseeded when the VM generation ID changes.
+.Pp
+Currently there is no cheaper way to detect VM generation ID changes
+than to query sysctl.

Index: src/sys/dev/acpi/acpi_vmgenid.c
diff -u /dev/null src/sys/dev/acpi/acpi_vmgenid.c:1.1
--- /dev/null	Mon Aug 26 13:38:29 2024
+++ src/sys/dev/acpi/acpi_vmgenid.c	Mon Aug 26 13:38:28 2024
@@ -0,0 +1,345 @@
+/*	$NetBSD: acpi_vmgenid.c,v 1.1 2024/08/26 13:38:28 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2024 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Virtual Machine Generation ID
+ *
+ *	The VMGENID is an 8-byte cookie shared between a VM host and VM
+ *	guest.  Whenever the host clones a VM, it changes the VMGENID
+ *	and sends an ACPI notification to the guest.
+ *
+ * References:
+ *
+ *	`Virtual Machine Generation ID', Microsoft, 2012-08-01.
+ *	http://go.microsoft.com/fwlink/?LinkId=260709
+ *
+ *	`Virtual Machine Generation ID Device', The QEMU Project
+ *	Developers.
+ *	https://www.qemu.org/docs/master/specs/vmgenid.html
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: acpi_vmgenid.c,v 1.1 2024/08/26 13:38:28 riastradh Exp $");
+
+#include <sys/device.h>
+#include <sys/entropy.h>
+#include <sys/module.h>
+#include <sys/rndsource.h>
+#include <sys/sysctl.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+#define	_COMPONENT	ACPI_RESOURCE_COMPONENT
+ACPI_MODULE_NAME	("acpi_vmgenid")
+
+struct acpivmgenid {
+	uint8_t		id[16];
+} __aligned(8);
+
+struct acpivmgenid_softc {
+	device_t			sc_dev;
+	struct acpi_devnode		*sc_node;
+	uint64_t			sc_paddr;
+	struct acpivmgenid		*sc_vaddr;
+	struct krndsource		sc_rndsource;
+	struct sysctllog		*sc_sysctllog;
+	const struct sysctlnode		*sc_sysctlroot;
+};
+
+static int acpivmgenid_match(device_t, cfdata_t, void *);
+static void acpivmgenid_attach(device_t, device_t, void *);
+static int acpivmgenid_detach(device_t, int);
+static void acpivmgenid_set(struct acpivmgenid_softc *, const char *);
+static void acpivmgenid_notify(ACPI_HANDLE, uint32_t, void *);
+static void acpivmgenid_reset(void *);
+static int acpivmgenid_sysctl(SYSCTLFN_ARGS);
+
+static const struct device_compatible_entry compat_data[] = {
+	{ .compat = "VM_Gen_Counter" },		/* from the Microsoft spec */
+	{ .compat = "VM_GEN_COUNTER" },		/* used by qemu */
+	{ .compat = "VMGENCTR" },		/* recognized by Linux */
+	DEVICE_COMPAT_EOL
+};
+
+CFATTACH_DECL_NEW(acpivmgenid, sizeof(struct acpivmgenid_softc),
+    acpivmgenid_match, acpivmgenid_attach, acpivmgenid_detach, NULL);
+
+static int
+acpivmgenid_match(device_t parent, cfdata_t match, void *aux)
+{
+	const struct acpi_attach_args *const aa = aux;
+
+	return acpi_compatible_match(aa, compat_data);
+}
+
+static void
+acpivmgenid_attach(device_t parent, device_t self, void *aux)
+{
+	struct acpivmgenid_softc *const sc = device_private(self);
+	const struct acpi_attach_args *const aa = aux;
+	ACPI_BUFFER addrbuf = {
+		.Pointer = NULL,
+		.Length = ACPI_ALLOCATE_BUFFER,
+	};
+	ACPI_OBJECT *addrobj, *addrarr;
+	ACPI_STATUS rv;
+	int error;
+
+	aprint_naive(": ACPI VM Generation ID\n");
+	aprint_normal(": ACPI VM Generation ID\n");
+
+	sc->sc_dev = self;
+	sc->sc_node = aa->aa_node;
+
+	/*
+	 * Get the address from the ADDR object, which is a package of
+	 * two 32-bit integers representing the low and high halves of
+	 * a 64-bit physical address.
+	 */
+	rv = AcpiEvaluateObjectTyped(sc->sc_node->ad_handle, "ADDR", NULL,
+	    &addrbuf, ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(rv)) {
+		aprint_error_dev(self, "failed to get ADDR: %s\n",
+		    AcpiFormatException(rv));
+		goto out;
+	}
+	addrobj = addrbuf.Pointer;
+	if (addrobj->Type != ACPI_TYPE_PACKAGE ||
+	    addrobj->Package.Count != 2) {
+		aprint_error_dev(self, "invalid ADDR\n");
+		goto out;
+	}
+	addrarr = addrobj->Package.Elements;
+	if (addrarr[0].Type != ACPI_TYPE_INTEGER ||
+	    addrarr[1].Type != ACPI_TYPE_INTEGER ||
+	    addrarr[0].Integer.Value > UINT32_MAX ||
+	    addrarr[1].Integer.Value > UINT32_MAX) {
+		aprint_error_dev(self, "invalid ADDR\n");
+		goto out;
+	}
+	sc->sc_paddr = (ACPI_PHYSICAL_ADDRESS)addrarr[0].Integer.Value;
+	sc->sc_paddr |= (ACPI_PHYSICAL_ADDRESS)addrarr[1].Integer.Value << 32;
+	aprint_normal_dev(self, "paddr=0x%"PRIx64"\n", (uint64_t)sc->sc_paddr);
+
+	/*
+	 * Map the physical address into virtual address space.
+	 */
+	sc->sc_vaddr = AcpiOsMapMemory(sc->sc_paddr, sizeof(*sc->sc_vaddr));
+	if (sc->sc_vaddr == NULL) {
+		aprint_error_dev(self, "failed to map address\n");
+		goto out;
+	}
+
+	/*
+	 * Register a random source so we can attribute samples.
+	 */
+	rnd_attach_source(&sc->sc_rndsource, device_xname(self),
+	    RND_TYPE_UNKNOWN, RND_FLAG_COLLECT_TIME|RND_FLAG_COLLECT_VALUE);
+
+	/*
+	 * Register an ACPI notifier so that we can detect changes.
+	 */
+	(void)acpi_register_notify(sc->sc_node, acpivmgenid_notify);
+
+	/*
+	 * Now that we have registered a random source and a notifier,
+	 * read out the first value.
+	 */
+	acpivmgenid_set(sc, "initial");
+
+	/*
+	 * Attach a sysctl tree, rooted at hw.acpivmgenidN.
+	 */
+	error = sysctl_createv(&sc->sc_sysctllog, 0, NULL, &sc->sc_sysctlroot,
+	    CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(self),
+	    SYSCTL_DESCR("Virtual Machine Generation ID device"),
+	    NULL, 0, NULL, 0,
+	    CTL_HW, CTL_CREATE, CTL_EOL);
+	if (error) {
+		aprint_error_dev(self, "failed to create sysctl hw.%s: %d\n",
+		    device_xname(self), error);
+		goto out;
+	}
+
+	/*
+	 * hw.acpivmgenidN.id (`struct', 16-byte array)
+	 */
+	error = sysctl_createv(&sc->sc_sysctllog, 0, &sc->sc_sysctlroot, NULL,
+	    CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_STRUCT,
+	    "id", SYSCTL_DESCR("Virtual Machine Generation ID"),
+	    &acpivmgenid_sysctl, 0, sc, sizeof(struct acpivmgenid),
+	    CTL_CREATE, CTL_EOL);
+	if (error) {
+		aprint_error_dev(self,
+		    "failed to create sysctl hw.%s.id: %d\n",
+		    device_xname(self), error);
+		goto out;
+	}
+
+	/*
+	 * hw.acpivmgenidN.paddr (64-bit integer)
+	 */
+	__CTASSERT(sizeof(ACPI_PHYSICAL_ADDRESS) == sizeof(quad_t));
+	error = sysctl_createv(&sc->sc_sysctllog, 0, &sc->sc_sysctlroot, NULL,
+	    CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_QUAD,
+	    "paddr", SYSCTL_DESCR("Physical address of VM Generation ID"),
+	    NULL, 0, &sc->sc_paddr, sizeof(sc->sc_paddr),
+	    CTL_CREATE, CTL_EOL);
+	if (error) {
+		aprint_error_dev(self,
+		    "failed to create sysctl hw.%s.paddr: %d\n",
+		    device_xname(self), error);
+		goto out;
+	}
+
+out:	ACPI_FREE(addrbuf.Pointer);
+}
+
+static int
+acpivmgenid_detach(device_t self, int flags)
+{
+	struct acpivmgenid_softc *const sc = device_private(self);
+	int error;
+
+	error = config_detach_children(self, flags);
+	if (error)
+		return error;
+
+	sysctl_teardown(&sc->sc_sysctllog);
+	acpi_deregister_notify(sc->sc_node);
+	rnd_detach_source(&sc->sc_rndsource);
+	if (sc->sc_vaddr) {
+		AcpiOsUnmapMemory(sc->sc_vaddr, sizeof(*sc->sc_vaddr));
+		sc->sc_vaddr = NULL;	/* paranoia */
+	}
+	sc->sc_paddr = 0;	/* paranoia */
+
+	return 0;
+}
+
+static void
+acpivmgenid_set(struct acpivmgenid_softc *sc, const char *prefix)
+{
+	struct acpivmgenid vmgenid;
+	char vmgenidstr[2*__arraycount(vmgenid.id) + 1];
+	unsigned i;
+
+	/*
+	 * Grab the current VM generation ID.  No obvious way to make
+	 * this atomic, so let's hope if it changes in the middle we'll
+	 * get another notification.
+	 */
+	memcpy(&vmgenid, sc->sc_vaddr, sizeof(vmgenid));
+
+	/*
+	 * Print the VM generation ID to the console for posterity.
+	 */
+	for (i = 0; i < __arraycount(vmgenid.id); i++) {
+		vmgenidstr[2*i] = "0123456789abcdef"[vmgenid.id[i] >> 4];
+		vmgenidstr[2*i + 1] = "0123456789abcdef"[vmgenid.id[i] & 0xf];
+	}
+	vmgenidstr[2*sizeof(vmgenid)] = '\0';
+	aprint_verbose_dev(sc->sc_dev, "%s: %s\n", prefix, vmgenidstr);
+
+	/*
+	 * Enter the new VM generation ID into the entropy pool.
+	 */
+	rnd_add_data(&sc->sc_rndsource, &vmgenid, sizeof(vmgenid), 0);
+}
+
+static void
+acpivmgenid_notify(ACPI_HANDLE hdl, uint32_t notify, void *opaque)
+{
+	const device_t self = opaque;
+	struct acpivmgenid_softc *const sc = device_private(self);
+
+	if (notify != 0x80) {
+		aprint_debug_dev(self, "unknown notify 0x%02x\n", notify);
+		return;
+	}
+
+	(void)AcpiOsExecute(OSL_NOTIFY_HANDLER, &acpivmgenid_reset, sc);
+}
+
+static void
+acpivmgenid_reset(void *cookie)
+{
+	struct acpivmgenid_softc *const sc = cookie;
+
+	/*
+	 * Grab the current VM generation ID to put it into the entropy
+	 * pool; then force consolidation so it affects all subsequent
+	 * draws from the entropy pool and the entropy epoch advances.
+	 *
+	 * XXX This should also reset the entropy count and request new
+	 * samples from all sources, but there currently isn't a good
+	 * way to do that after boot.
+	 */
+	acpivmgenid_set(sc, "cloned");
+	entropy_consolidate();
+}
+
+static int
+acpivmgenid_sysctl(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node = *rnode;
+	struct acpivmgenid_softc *const sc = node.sysctl_data;
+
+	node.sysctl_data = sc->sc_vaddr;
+	return sysctl_lookup(SYSCTLFN_CALL(&node));
+}
+
+MODULE(MODULE_CLASS_DRIVER, acpivmgenid, NULL);
+
+#ifdef _MODULE
+#include "ioconf.c"
+#endif
+
+static int
+acpivmgenid_modcmd(modcmd_t cmd, void *opaque)
+{
+	int error = 0;
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+#ifdef _MODULE
+		error = config_init_component(cfdriver_ioconf_acpivmgenid,
+		    cfattach_ioconf_acpivmgenid, cfdata_ioconf_acpivmgenid);
+#endif
+		return error;
+	case MODULE_CMD_FINI:
+#ifdef _MODULE
+		error = config_fini_component(cfdriver_ioconf_acpivmgenid,
+		    cfattach_ioconf_acpivmgenid, cfdata_ioconf_acpivmgenid);
+#endif
+		return error;
+	default:
+		return ENOTTY;
+	}
+}

Index: src/sys/modules/acpivmgenid/Makefile
diff -u /dev/null src/sys/modules/acpivmgenid/Makefile:1.1
--- /dev/null	Mon Aug 26 13:38:29 2024
+++ src/sys/modules/acpivmgenid/Makefile	Mon Aug 26 13:38:28 2024
@@ -0,0 +1,11 @@
+#	$NetBSD: Makefile,v 1.1 2024/08/26 13:38:28 riastradh Exp $
+
+.include "../Makefile.inc"
+
+.PATH:	${S}/dev/acpi
+
+KMOD=	acpivmgenid
+IOCONF=	acpivmgenid.ioconf
+SRCS=	acpi_vmgenid.c
+
+.include <bsd.kmodule.mk>
Index: src/sys/modules/acpivmgenid/acpivmgenid.ioconf
diff -u /dev/null src/sys/modules/acpivmgenid/acpivmgenid.ioconf:1.1
--- /dev/null	Mon Aug 26 13:38:29 2024
+++ src/sys/modules/acpivmgenid/acpivmgenid.ioconf	Mon Aug 26 13:38:29 2024
@@ -0,0 +1,10 @@
+#	$NetBSD: acpivmgenid.ioconf,v 1.1 2024/08/26 13:38:29 riastradh Exp $
+
+ioconf acpivmgenid
+
+include "conf/files"
+include "dev/acpi/files.acpi"
+
+pseudo-root acpi*
+
+acpivmgenid*	at acpi?

Reply via email to