On Fri, Feb 25, 2022 at 12:24 PM Ard Biesheuvel <ardb@xxxxxxxxxx> wrote: > > > @@ -13,6 +13,15 @@ menuconfig VIRT_DRIVERS > > > > if VIRT_DRIVERS > > > > +config VMGENID > > + tristate "Virtual Machine Generation ID driver" > > + default y > > Please make this default m - this code can run as a module and the > feature it relies on is discoverable by udev Will do. > > index 000000000000..5da4dc8f25e3 > > --- /dev/null > > +++ b/drivers/virt/vmgenid.c > > @@ -0,0 +1,121 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Virtual Machine Generation ID driver > > + * > > + * Copyright (C) 2022 Jason A. Donenfeld <Jason@xxxxxxxxx>. All Rights Reserved. > > + * Copyright (C) 2020 Amazon. All rights reserved. > > + * Copyright (C) 2018 Red Hat Inc. All rights reserved. > > + */ > > + > > +#include <linux/kernel.h> > > +#include <linux/module.h> > > +#include <linux/acpi.h> > > +#include <linux/random.h> > > + > > +ACPI_MODULE_NAME("vmgenid"); > > + > > +enum { VMGENID_SIZE = 16 }; > > + > > +static struct { > > + u8 this_id[VMGENID_SIZE]; > > + u8 *next_id; > > +} state; > > + > > This state is singular > > > > +static int vmgenid_acpi_add(struct acpi_device *device) > > +{ > > ... whereas this may be called for multiple instances of the device. > This likely makes no sense, so it is better to reject it here. Like, return early if it's called a second time? I can do that. > > > + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER }; > > + union acpi_object *pss; > > + phys_addr_t phys_addr; > > + acpi_status status; > > + int ret = 0; > > + > > + if (!device) > > + return -EINVAL; > > + > > + status = acpi_evaluate_object(device->handle, "ADDR", NULL, &buffer); > > + if (ACPI_FAILURE(status)) { > > + ACPI_EXCEPTION((AE_INFO, status, "Evaluating ADDR")); > > + return -ENODEV; > > + } > > + pss = buffer.pointer; > > + if (!pss || pss->type != ACPI_TYPE_PACKAGE || pss->package.count != 2 || > > + pss->package.elements[0].type != ACPI_TYPE_INTEGER || > > + pss->package.elements[1].type != ACPI_TYPE_INTEGER) { > > + ret = -EINVAL; > > + goto out; > > + } > > + > > + phys_addr = (pss->package.elements[0].integer.value << 0) | > > + (pss->package.elements[1].integer.value << 32); > > + state.next_id = acpi_os_map_memory(phys_addr, VMGENID_SIZE); > > No need to use acpi_os_map_memory() here, plain memremap() should be fine. As we discussed online, I'll use dev_memremap(), and then get rid of the `.remove = ` function all together. > > + acpi_os_unmap_memory(state.next_id, VMGENID_SIZE); > > memunmap() here And then as discussed, this goes away too. > > > + state.next_id = NULL; > > + return 0; > > +} > > + > > +static void vmgenid_acpi_notify(struct acpi_device *device, u32 event) > > +{ > > + u8 old_id[VMGENID_SIZE]; > > + > > + if (!device || acpi_driver_data(device) != &state) > > + return; > > + memcpy(old_id, state.this_id, sizeof(old_id)); > > + memcpy(state.this_id, state.next_id, sizeof(state.this_id)); > > + if (!memcmp(old_id, state.this_id, sizeof(old_id))) > > + return; > > Is this little dance really necessary? I.e., can we just do > > add_vmfork_randomness(state.next_id, VMGENID_SIZE) > > and be done with it? Yes it is. vmfork induces a "premature-next" which we really should not do unless it's really necessary. It torches the whole entropy pool. In the even that this notifier fires but the ID hasn't changed, we shouldn't touch anything. Thanks for the review. v+1 coming up shortly.