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?