Index: usr.sbin/bhyve/Makefile =================================================================== --- usr.sbin/bhyve/Makefile +++ usr.sbin/bhyve/Makefile @@ -67,6 +67,7 @@ usb_mouse.c \ virtio.c \ vga.c \ + vmgenc.c \ xmsr.c \ spinup_ap.c \ iov.c Index: usr.sbin/bhyve/acpi.c =================================================================== --- usr.sbin/bhyve/acpi.c +++ usr.sbin/bhyve/acpi.c @@ -74,6 +74,7 @@ #include "bhyverun.h" #include "acpi.h" #include "pci_emul.h" +#include "vmgenc.h" /* * Define the base address of the ACPI tables, the sizes of some tables, @@ -756,6 +757,9 @@ dsdt_line(" })"); dsdt_line(" }"); dsdt_line(" }"); + + vmgenc_write_dsdt(); + dsdt_line("}"); if (dsdt_error != 0) Index: usr.sbin/bhyve/bhyverun.c =================================================================== --- usr.sbin/bhyve/bhyverun.c +++ usr.sbin/bhyve/bhyverun.c @@ -84,6 +84,7 @@ #include "xmsr.h" #include "spinup_ap.h" #include "rtc.h" +#include "vmgenc.h" #define GUEST_NIO_PORT 0x488 /* guest upcalls via i/o port */ @@ -1163,6 +1164,8 @@ rtc_init(ctx, rtc_localtime); sci_init(ctx); + if (acpi) + vmgenc_init(ctx); /* * Exit if a device emulation finds an error in its initilization Index: usr.sbin/bhyve/vmgenc.h =================================================================== --- /dev/null +++ usr.sbin/bhyve/vmgenc.h @@ -0,0 +1,31 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright 2020 Conrad Meyer . 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 NETAPP, INC ``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 NETAPP, INC 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. + * + * $FreeBSD$ + */ +#pragma once +void vmgenc_init(struct vmctx *); +void vmgenc_write_dsdt(void); Index: usr.sbin/bhyve/vmgenc.c =================================================================== --- /dev/null +++ usr.sbin/bhyve/vmgenc.c @@ -0,0 +1,160 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright 2020 Conrad Meyer . 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 NETAPP, INC ``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 NETAPP, INC 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. + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "acpi.h" +#include "mem.h" +#include "vmgenc.h" + +static struct uuid vmgen_id; +static uint64_t vmgen_gpa; + +static int +vmgenc_mem_handler(struct vmctx *ctx __unused, int vcpu __unused, int dir, + uint64_t addr, int size, uint64_t *val, void *arg1 __unused, + long arg2 __unused) +{ + uint64_t offset; + + /* Ignore writes. */ + if (dir == MEM_F_WRITE) + return (0); + + assert(addr >= vmgen_gpa && size <= sizeof(vmgen_id) && + addr + size <= vmgen_gpa + sizeof(vmgen_id) && + ((size == 8 && (addr & 0x7) == 0) || + (size == 4 && (addr & 0x3) == 0))); + + offset = addr - vmgen_gpa; + + if (size == 8) + *val = *(uint64_t *)((char *)&vmgen_id + offset); + else + *val = *(uint32_t *)((char *)&vmgen_id + offset); + return (0); +} + +void +vmgenc_init(struct vmctx *ctx) +{ + struct mem_range mr; + uint32_t lowmem_gpa; + int error; + + /* + * Slice off some PCI hole memory, which is not allocatable to the + * guest operating system's general use. + */ + lowmem_gpa = vm_get_lowmem_limit(ctx); + /* + * GUID must be 8-byte aligned, per spec. + */ + lowmem_gpa = roundup2(lowmem_gpa, 8); + vmgen_gpa = lowmem_gpa; + /* + * Ostensibly it needs to be cachable, but we don't attempt to enforce + * that at all. + */ + vm_set_lowmem_limit(ctx, lowmem_gpa + sizeof(vmgen_id)); + + /* + * It is basically harmless to always generate a random ID when + * starting a VM. + */ + error = getentropy(&vmgen_id, sizeof(vmgen_id)); + if (error == -1) + err(4, "vmgenc: getentropy"); + + mr = (struct mem_range) { + .name = "vmgenc", + .base = vmgen_gpa, + .size = sizeof(vmgen_id), + .flags = MEM_F_READ | MEM_F_IMMUTABLE, + .handler = vmgenc_mem_handler, + }; + error = register_mem(&mr); + if (error != 0) + errc(4, error, "vmgenc: register_mem"); +} + +void +vmgenc_write_dsdt(void) +{ + dsdt_line(""); + dsdt_indent(1); + dsdt_line("Scope (_SB)"); + dsdt_line("{"); + + dsdt_line(" Device (GENC)"); + dsdt_line(" {"); + + dsdt_indent(2); + dsdt_line("Name (_CID, \"VM_Gen_Counter\")"); + dsdt_line("Method (_HID, 0, NotSerialized)"); + dsdt_line("{"); + dsdt_line(" Return (\"Bhyve_V_Gen_Counter_V0\")"); + dsdt_line("}"); + dsdt_line("Name (_UID, 0)"); + dsdt_line("Name (_DDN, \"VM_Gen_Counter\")"); + dsdt_line("Method (ADDR, 0, NotSerialized)"); + dsdt_line("{"); + dsdt_indent(1); + dsdt_line("Return (Package (0x02)"); + dsdt_line("{"); + dsdt_line(" 0x%08x,", (uint32_t)vmgen_gpa); + dsdt_line(" 0x%08x", (uint32_t)(vmgen_gpa >> 32)); + dsdt_line("})"); + + dsdt_unindent(1); + dsdt_line("}"); /* Method (ADDR) */ + + dsdt_unindent(2); + dsdt_line(" }"); /* Device (GENC) */ + + dsdt_line("}"); /* Scope (_SB) */ + dsdt_line(""); + dsdt_unindent(1); +}