xref: /freebsd/usr.sbin/bhyve/amd64/bhyverun_machdep.c (revision f1d705d4f431a5553aa5e64310bdc703ba27eab4)
1e20b74daSMark Johnston /*-
2e20b74daSMark Johnston  * SPDX-License-Identifier: BSD-2-Clause
3e20b74daSMark Johnston  *
4e20b74daSMark Johnston  * Copyright (c) 2011 NetApp, Inc.
5e20b74daSMark Johnston  * All rights reserved.
6e20b74daSMark Johnston  *
7e20b74daSMark Johnston  * Redistribution and use in source and binary forms, with or without
8e20b74daSMark Johnston  * modification, are permitted provided that the following conditions
9e20b74daSMark Johnston  * are met:
10e20b74daSMark Johnston  * 1. Redistributions of source code must retain the above copyright
11e20b74daSMark Johnston  *    notice, this list of conditions and the following disclaimer.
12e20b74daSMark Johnston  * 2. Redistributions in binary form must reproduce the above copyright
13e20b74daSMark Johnston  *    notice, this list of conditions and the following disclaimer in the
14e20b74daSMark Johnston  *    documentation and/or other materials provided with the distribution.
15e20b74daSMark Johnston  *
16e20b74daSMark Johnston  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17e20b74daSMark Johnston  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18e20b74daSMark Johnston  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19e20b74daSMark Johnston  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20e20b74daSMark Johnston  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21e20b74daSMark Johnston  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22e20b74daSMark Johnston  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23e20b74daSMark Johnston  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24e20b74daSMark Johnston  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25e20b74daSMark Johnston  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26e20b74daSMark Johnston  * SUCH DAMAGE.
27e20b74daSMark Johnston  */
28e20b74daSMark Johnston 
29e20b74daSMark Johnston #include <assert.h>
30e20b74daSMark Johnston #include <err.h>
31e20b74daSMark Johnston #include <stdbool.h>
32e20b74daSMark Johnston #include <stdlib.h>
33981f9f74SMark Johnston #include <sysexits.h>
34e20b74daSMark Johnston 
35e20b74daSMark Johnston #include <vmmapi.h>
36e20b74daSMark Johnston 
37f82af74cSMark Johnston #include "acpi.h"
38f82af74cSMark Johnston #include "atkbdc.h"
39e20b74daSMark Johnston #include "bhyverun.h"
4043caa2e8SMark Johnston #include "bootrom.h"
41e20b74daSMark Johnston #include "config.h"
42b0936440SJohn Baldwin #include "debug.h"
43f82af74cSMark Johnston #include "e820.h"
44f82af74cSMark Johnston #include "fwctl.h"
45f82af74cSMark Johnston #include "ioapic.h"
46f82af74cSMark Johnston #include "inout.h"
47f82af74cSMark Johnston #include "kernemu_dev.h"
48f82af74cSMark Johnston #include "mptbl.h"
49981f9f74SMark Johnston #include "pci_emul.h"
50f82af74cSMark Johnston #include "pci_irq.h"
51e20b74daSMark Johnston #include "pci_lpc.h"
52f82af74cSMark Johnston #include "rtc.h"
53f82af74cSMark Johnston #include "smbiostbl.h"
54f82af74cSMark Johnston #include "xmsr.h"
55e20b74daSMark Johnston 
56e20b74daSMark Johnston void
bhyve_init_config(void)57e20b74daSMark Johnston bhyve_init_config(void)
58e20b74daSMark Johnston {
59e20b74daSMark Johnston 	init_config();
60e20b74daSMark Johnston 
61e20b74daSMark Johnston 	/* Set default values prior to option parsing. */
62e20b74daSMark Johnston 	set_config_bool("acpi_tables", true);
63e20b74daSMark Johnston 	set_config_bool("acpi_tables_in_memory", true);
64e20b74daSMark Johnston 	set_config_value("memory.size", "256M");
65e20b74daSMark Johnston 	set_config_bool("x86.strictmsr", true);
66a27328eaSbrendabrandy 	set_config_bool("x86.verbosemsr", false);
67e20b74daSMark Johnston 	set_config_value("lpc.fwcfg", "bhyve");
68e20b74daSMark Johnston }
69e20b74daSMark Johnston 
70e20b74daSMark Johnston void
bhyve_usage(int code)71981f9f74SMark Johnston bhyve_usage(int code)
72981f9f74SMark Johnston {
73981f9f74SMark Johnston 	const char *progname;
74981f9f74SMark Johnston 
75981f9f74SMark Johnston 	progname = getprogname();
76981f9f74SMark Johnston 
77981f9f74SMark Johnston 	fprintf(stderr,
7810758471SMark Johnston 	    "Usage: %s [-aCDeHhPSuWwxY]\n"
79981f9f74SMark Johnston 	    "       %*s [-c [[cpus=]numcpus][,sockets=n][,cores=n][,threads=n]]\n"
80981f9f74SMark Johnston 	    "       %*s [-G port] [-k config_file] [-l lpc] [-m mem] [-o var=value]\n"
81981f9f74SMark Johnston 	    "       %*s [-p vcpu:hostcpu] [-r file] [-s pci] [-U uuid] vmname\n"
82981f9f74SMark Johnston 	    "       -a: local apic is in xAPIC mode (deprecated)\n"
83981f9f74SMark Johnston 	    "       -C: include guest memory in core file\n"
84981f9f74SMark Johnston 	    "       -c: number of CPUs and/or topology specification\n"
85981f9f74SMark Johnston 	    "       -D: destroy on power-off\n"
86981f9f74SMark Johnston 	    "       -e: exit on unhandled I/O access\n"
87981f9f74SMark Johnston 	    "       -G: start a debug server\n"
88981f9f74SMark Johnston 	    "       -H: vmexit from the guest on HLT\n"
89981f9f74SMark Johnston 	    "       -h: help\n"
90981f9f74SMark Johnston 	    "       -k: key=value flat config file\n"
91981f9f74SMark Johnston 	    "       -K: PS2 keyboard layout\n"
92981f9f74SMark Johnston 	    "       -l: LPC device configuration\n"
93981f9f74SMark Johnston 	    "       -m: memory size\n"
94*f1d705d4SBojan Novković 	    "       -n: NUMA domain specification\n"
95981f9f74SMark Johnston 	    "       -o: set config 'var' to 'value'\n"
96981f9f74SMark Johnston 	    "       -P: vmexit from the guest on pause\n"
97981f9f74SMark Johnston 	    "       -p: pin 'vcpu' to 'hostcpu'\n"
98981f9f74SMark Johnston #ifdef BHYVE_SNAPSHOT
99981f9f74SMark Johnston 	    "       -r: path to checkpoint file\n"
100981f9f74SMark Johnston #endif
101981f9f74SMark Johnston 	    "       -S: guest memory cannot be swapped\n"
102981f9f74SMark Johnston 	    "       -s: <slot,driver,configinfo> PCI slot config\n"
103981f9f74SMark Johnston 	    "       -U: UUID\n"
104981f9f74SMark Johnston 	    "       -u: RTC keeps UTC time\n"
105981f9f74SMark Johnston 	    "       -W: force virtio to use single-vector MSI\n"
106981f9f74SMark Johnston 	    "       -w: ignore unimplemented MSRs\n"
107981f9f74SMark Johnston 	    "       -x: local APIC is in x2APIC mode\n"
108981f9f74SMark Johnston 	    "       -Y: disable MPtable generation\n",
109981f9f74SMark Johnston 	    progname, (int)strlen(progname), "", (int)strlen(progname), "",
110981f9f74SMark Johnston 	    (int)strlen(progname), "");
111981f9f74SMark Johnston 	exit(code);
112981f9f74SMark Johnston }
113981f9f74SMark Johnston 
114981f9f74SMark Johnston void
bhyve_optparse(int argc,char ** argv)115981f9f74SMark Johnston bhyve_optparse(int argc, char **argv)
116981f9f74SMark Johnston {
117981f9f74SMark Johnston 	const char *optstr;
118981f9f74SMark Johnston 	int c;
119981f9f74SMark Johnston 
120981f9f74SMark Johnston #ifdef BHYVE_SNAPSHOT
121*f1d705d4SBojan Novković 	optstr = "aehuwxACDHIPSWYk:f:o:p:G:c:s:m:n:l:K:U:r:";
122981f9f74SMark Johnston #else
123*f1d705d4SBojan Novković 	optstr = "aehuwxACDHIPSWYk:f:o:p:G:c:s:m:n:l:K:U:";
124981f9f74SMark Johnston #endif
125981f9f74SMark Johnston 	while ((c = getopt(argc, argv, optstr)) != -1) {
126981f9f74SMark Johnston 		switch (c) {
127981f9f74SMark Johnston 		case 'a':
128981f9f74SMark Johnston 			set_config_bool("x86.x2apic", false);
129981f9f74SMark Johnston 			break;
130981f9f74SMark Johnston 		case 'A':
131981f9f74SMark Johnston 			/*
132981f9f74SMark Johnston 			 * NOP. For backward compatibility. Most systems don't
133981f9f74SMark Johnston 			 * work properly without sane ACPI tables. Therefore,
134981f9f74SMark Johnston 			 * we're always generating them.
135981f9f74SMark Johnston 			 */
136981f9f74SMark Johnston 			break;
137981f9f74SMark Johnston 		case 'D':
138981f9f74SMark Johnston 			set_config_bool("destroy_on_poweroff", true);
139981f9f74SMark Johnston 			break;
140981f9f74SMark Johnston 		case 'p':
141981f9f74SMark Johnston 			if (bhyve_pincpu_parse(optarg) != 0) {
142981f9f74SMark Johnston 				errx(EX_USAGE, "invalid vcpu pinning "
143981f9f74SMark Johnston 				    "configuration '%s'", optarg);
144981f9f74SMark Johnston 			}
145981f9f74SMark Johnston 			break;
146981f9f74SMark Johnston 		case 'c':
147981f9f74SMark Johnston 			if (bhyve_topology_parse(optarg) != 0) {
148981f9f74SMark Johnston 			    errx(EX_USAGE, "invalid cpu topology "
149981f9f74SMark Johnston 				"'%s'", optarg);
150981f9f74SMark Johnston 			}
151981f9f74SMark Johnston 			break;
152981f9f74SMark Johnston 		case 'C':
153981f9f74SMark Johnston 			set_config_bool("memory.guest_in_core", true);
154981f9f74SMark Johnston 			break;
155981f9f74SMark Johnston 		case 'f':
156981f9f74SMark Johnston 			if (qemu_fwcfg_parse_cmdline_arg(optarg) != 0) {
157981f9f74SMark Johnston 				errx(EX_USAGE, "invalid fwcfg item '%s'",
158981f9f74SMark Johnston 				    optarg);
159981f9f74SMark Johnston 			}
160981f9f74SMark Johnston 			break;
161981f9f74SMark Johnston 		case 'G':
162981f9f74SMark Johnston 			bhyve_parse_gdb_options(optarg);
163981f9f74SMark Johnston 			break;
164981f9f74SMark Johnston 		case 'k':
165981f9f74SMark Johnston 			bhyve_parse_simple_config_file(optarg);
166981f9f74SMark Johnston 			break;
167981f9f74SMark Johnston 		case 'K':
168981f9f74SMark Johnston 			set_config_value("keyboard.layout", optarg);
169981f9f74SMark Johnston 			break;
170981f9f74SMark Johnston 		case 'l':
171981f9f74SMark Johnston 			if (strncmp(optarg, "help", strlen(optarg)) == 0) {
172981f9f74SMark Johnston 				lpc_print_supported_devices();
173981f9f74SMark Johnston 				exit(0);
174981f9f74SMark Johnston 			} else if (lpc_device_parse(optarg) != 0) {
175981f9f74SMark Johnston 				errx(EX_USAGE, "invalid lpc device "
176981f9f74SMark Johnston 				    "configuration '%s'", optarg);
177981f9f74SMark Johnston 			}
178981f9f74SMark Johnston 			break;
179981f9f74SMark Johnston #ifdef BHYVE_SNAPSHOT
180981f9f74SMark Johnston 		case 'r':
181981f9f74SMark Johnston 			restore_file = optarg;
182981f9f74SMark Johnston 			break;
183981f9f74SMark Johnston #endif
184981f9f74SMark Johnston 		case 's':
185981f9f74SMark Johnston 			if (strncmp(optarg, "help", strlen(optarg)) == 0) {
186981f9f74SMark Johnston 				pci_print_supported_devices();
187981f9f74SMark Johnston 				exit(0);
188981f9f74SMark Johnston 			} else if (pci_parse_slot(optarg) != 0)
189981f9f74SMark Johnston 				exit(4);
190981f9f74SMark Johnston 			else
191981f9f74SMark Johnston 				break;
192981f9f74SMark Johnston 		case 'S':
193981f9f74SMark Johnston 			set_config_bool("memory.wired", true);
194981f9f74SMark Johnston 			break;
195981f9f74SMark Johnston 		case 'm':
196981f9f74SMark Johnston 			set_config_value("memory.size", optarg);
197981f9f74SMark Johnston 			break;
198*f1d705d4SBojan Novković 		case 'n':
199*f1d705d4SBojan Novković 			if (bhyve_numa_parse(optarg) != 0)
200*f1d705d4SBojan Novković 				errx(EX_USAGE,
201*f1d705d4SBojan Novković 				    "invalid NUMA configuration "
202*f1d705d4SBojan Novković 				    "'%s'",
203*f1d705d4SBojan Novković 				    optarg);
204*f1d705d4SBojan Novković 			if (!get_config_bool("acpi_tables"))
205*f1d705d4SBojan Novković 				errx(EX_USAGE, "NUMA emulation requires ACPI");
206*f1d705d4SBojan Novković 			break;
207981f9f74SMark Johnston 		case 'o':
208981f9f74SMark Johnston 			if (!bhyve_parse_config_option(optarg)) {
209981f9f74SMark Johnston 				errx(EX_USAGE,
210981f9f74SMark Johnston 				    "invalid configuration option '%s'",
211981f9f74SMark Johnston 				    optarg);
212981f9f74SMark Johnston 			}
213981f9f74SMark Johnston 			break;
214981f9f74SMark Johnston 		case 'H':
215981f9f74SMark Johnston 			set_config_bool("x86.vmexit_on_hlt", true);
216981f9f74SMark Johnston 			break;
217981f9f74SMark Johnston 		case 'I':
218981f9f74SMark Johnston 			/*
219981f9f74SMark Johnston 			 * The "-I" option was used to add an ioapic to the
220981f9f74SMark Johnston 			 * virtual machine.
221981f9f74SMark Johnston 			 *
222981f9f74SMark Johnston 			 * An ioapic is now provided unconditionally for each
223981f9f74SMark Johnston 			 * virtual machine and this option is now deprecated.
224981f9f74SMark Johnston 			 */
225981f9f74SMark Johnston 			break;
226981f9f74SMark Johnston 		case 'P':
227981f9f74SMark Johnston 			set_config_bool("x86.vmexit_on_pause", true);
228981f9f74SMark Johnston 			break;
229981f9f74SMark Johnston 		case 'e':
230981f9f74SMark Johnston 			set_config_bool("x86.strictio", true);
231981f9f74SMark Johnston 			break;
232981f9f74SMark Johnston 		case 'u':
233981f9f74SMark Johnston 			set_config_bool("rtc.use_localtime", false);
234981f9f74SMark Johnston 			break;
235981f9f74SMark Johnston 		case 'U':
236981f9f74SMark Johnston 			set_config_value("uuid", optarg);
237981f9f74SMark Johnston 			break;
238981f9f74SMark Johnston 		case 'w':
239981f9f74SMark Johnston 			set_config_bool("x86.strictmsr", false);
240981f9f74SMark Johnston 			break;
241981f9f74SMark Johnston 		case 'W':
242981f9f74SMark Johnston 			set_config_bool("virtio_msix", false);
243981f9f74SMark Johnston 			break;
244981f9f74SMark Johnston 		case 'x':
245981f9f74SMark Johnston 			set_config_bool("x86.x2apic", true);
246981f9f74SMark Johnston 			break;
247981f9f74SMark Johnston 		case 'Y':
248981f9f74SMark Johnston 			set_config_bool("x86.mptable", false);
249981f9f74SMark Johnston 			break;
250981f9f74SMark Johnston 		case 'h':
251981f9f74SMark Johnston 			bhyve_usage(0);
252981f9f74SMark Johnston 		default:
253981f9f74SMark Johnston 			bhyve_usage(1);
254981f9f74SMark Johnston 		}
255981f9f74SMark Johnston 	}
25643caa2e8SMark Johnston 
25743caa2e8SMark Johnston 	/* Handle backwards compatibility aliases in config options. */
25843caa2e8SMark Johnston 	if (get_config_value("lpc.bootrom") != NULL &&
25943caa2e8SMark Johnston 	    get_config_value("bootrom") == NULL) {
26043caa2e8SMark Johnston 		warnx("lpc.bootrom is deprecated, use '-o bootrom' instead");
26143caa2e8SMark Johnston 		set_config_value("bootrom", get_config_value("lpc.bootrom"));
26243caa2e8SMark Johnston 	}
26343caa2e8SMark Johnston 	if (get_config_value("lpc.bootvars") != NULL &&
26443caa2e8SMark Johnston 	    get_config_value("bootvars") == NULL) {
26543caa2e8SMark Johnston 		warnx("lpc.bootvars is deprecated, use '-o bootvars' instead");
26643caa2e8SMark Johnston 		set_config_value("bootvars", get_config_value("lpc.bootvars"));
26743caa2e8SMark Johnston 	}
268981f9f74SMark Johnston }
269981f9f74SMark Johnston 
270981f9f74SMark Johnston void
bhyve_init_vcpu(struct vcpu * vcpu)271e20b74daSMark Johnston bhyve_init_vcpu(struct vcpu *vcpu)
272e20b74daSMark Johnston {
273e20b74daSMark Johnston 	int err, tmp;
274e20b74daSMark Johnston 
275e20b74daSMark Johnston 	if (get_config_bool_default("x86.vmexit_on_hlt", false)) {
276e20b74daSMark Johnston 		err = vm_get_capability(vcpu, VM_CAP_HALT_EXIT, &tmp);
277e20b74daSMark Johnston 		if (err < 0) {
278b0936440SJohn Baldwin 			EPRINTLN("VM exit on HLT not supported");
279e20b74daSMark Johnston 			exit(4);
280e20b74daSMark Johnston 		}
281e20b74daSMark Johnston 		vm_set_capability(vcpu, VM_CAP_HALT_EXIT, 1);
282e20b74daSMark Johnston 	}
283e20b74daSMark Johnston 
284e20b74daSMark Johnston 	if (get_config_bool_default("x86.vmexit_on_pause", false)) {
285e20b74daSMark Johnston 		/*
286e20b74daSMark Johnston 		 * pause exit support required for this mode
287e20b74daSMark Johnston 		 */
288e20b74daSMark Johnston 		err = vm_get_capability(vcpu, VM_CAP_PAUSE_EXIT, &tmp);
289e20b74daSMark Johnston 		if (err < 0) {
290b0936440SJohn Baldwin 			EPRINTLN("SMP mux requested, no pause support");
291e20b74daSMark Johnston 			exit(4);
292e20b74daSMark Johnston 		}
293e20b74daSMark Johnston 		vm_set_capability(vcpu, VM_CAP_PAUSE_EXIT, 1);
294e20b74daSMark Johnston 	}
295e20b74daSMark Johnston 
296e20b74daSMark Johnston 	if (get_config_bool_default("x86.x2apic", false))
297e20b74daSMark Johnston 		err = vm_set_x2apic_state(vcpu, X2APIC_ENABLED);
298e20b74daSMark Johnston 	else
299e20b74daSMark Johnston 		err = vm_set_x2apic_state(vcpu, X2APIC_DISABLED);
300e20b74daSMark Johnston 
301e20b74daSMark Johnston 	if (err) {
302b0936440SJohn Baldwin 		EPRINTLN("Unable to set x2apic state (%d)", err);
303e20b74daSMark Johnston 		exit(4);
304e20b74daSMark Johnston 	}
305e20b74daSMark Johnston 
306e20b74daSMark Johnston 	vm_set_capability(vcpu, VM_CAP_ENABLE_INVPCID, 1);
307e20b74daSMark Johnston 
308e20b74daSMark Johnston 	err = vm_set_capability(vcpu, VM_CAP_IPI_EXIT, 1);
309e20b74daSMark Johnston 	assert(err == 0);
310e20b74daSMark Johnston }
311e20b74daSMark Johnston 
312e20b74daSMark Johnston void
bhyve_start_vcpu(struct vcpu * vcpu,bool bsp)313e20b74daSMark Johnston bhyve_start_vcpu(struct vcpu *vcpu, bool bsp)
314e20b74daSMark Johnston {
315e20b74daSMark Johnston 	int error;
316e20b74daSMark Johnston 
317e20b74daSMark Johnston 	if (bsp) {
31843caa2e8SMark Johnston 		if (bootrom_boot()) {
319e20b74daSMark Johnston 			error = vm_set_capability(vcpu,
320e20b74daSMark Johnston 			    VM_CAP_UNRESTRICTED_GUEST, 1);
321e20b74daSMark Johnston 			if (error != 0) {
322e20b74daSMark Johnston 				err(4, "ROM boot failed: unrestricted guest "
323e20b74daSMark Johnston 				    "capability not available");
324e20b74daSMark Johnston 			}
325e20b74daSMark Johnston 			error = vcpu_reset(vcpu);
326e20b74daSMark Johnston 			assert(error == 0);
327e20b74daSMark Johnston 		}
328e20b74daSMark Johnston 	} else {
329e20b74daSMark Johnston 		bhyve_init_vcpu(vcpu);
330e20b74daSMark Johnston 
331e20b74daSMark Johnston 		/*
332e20b74daSMark Johnston 		 * Enable the 'unrestricted guest' mode for APs.
333e20b74daSMark Johnston 		 *
334e20b74daSMark Johnston 		 * APs startup in power-on 16-bit mode.
335e20b74daSMark Johnston 		 */
336e20b74daSMark Johnston 		error = vm_set_capability(vcpu, VM_CAP_UNRESTRICTED_GUEST, 1);
337e20b74daSMark Johnston 		assert(error == 0);
338e20b74daSMark Johnston 	}
339e20b74daSMark Johnston 
340e20b74daSMark Johnston 	fbsdrun_addcpu(vcpu_id(vcpu));
341e20b74daSMark Johnston }
342f82af74cSMark Johnston 
343f82af74cSMark Johnston int
bhyve_init_platform(struct vmctx * ctx,struct vcpu * bsp __unused)344f82af74cSMark Johnston bhyve_init_platform(struct vmctx *ctx, struct vcpu *bsp __unused)
345f82af74cSMark Johnston {
346f82af74cSMark Johnston 	int error;
347f82af74cSMark Johnston 
348f82af74cSMark Johnston 	error = init_msr();
349f82af74cSMark Johnston 	if (error != 0)
350f82af74cSMark Johnston 		return (error);
351f82af74cSMark Johnston 	init_inout();
352f82af74cSMark Johnston 	kernemu_dev_init();
353f82af74cSMark Johnston 	atkbdc_init(ctx);
354f82af74cSMark Johnston 	pci_irq_init(ctx);
355f82af74cSMark Johnston 	ioapic_init(ctx);
356f82af74cSMark Johnston 	rtc_init(ctx);
357f82af74cSMark Johnston 	sci_init(ctx);
358f82af74cSMark Johnston 	error = e820_init(ctx);
359f82af74cSMark Johnston 	if (error != 0)
360f82af74cSMark Johnston 		return (error);
36143caa2e8SMark Johnston 	error = bootrom_loadrom(ctx);
36243caa2e8SMark Johnston 	if (error != 0)
36343caa2e8SMark Johnston 		return (error);
364f82af74cSMark Johnston 
365f82af74cSMark Johnston 	return (0);
366f82af74cSMark Johnston }
367f82af74cSMark Johnston 
368f82af74cSMark Johnston int
bhyve_init_platform_late(struct vmctx * ctx,struct vcpu * bsp __unused)369f82af74cSMark Johnston bhyve_init_platform_late(struct vmctx *ctx, struct vcpu *bsp __unused)
370f82af74cSMark Johnston {
371f82af74cSMark Johnston 	int error;
372f82af74cSMark Johnston 
373f82af74cSMark Johnston 	if (get_config_bool_default("x86.mptable", true)) {
374f82af74cSMark Johnston 		error = mptable_build(ctx, guest_ncpus);
375f82af74cSMark Johnston 		if (error != 0)
376f82af74cSMark Johnston 			return (error);
377f82af74cSMark Johnston 	}
378f82af74cSMark Johnston 	error = smbios_build(ctx);
379f82af74cSMark Johnston 	if (error != 0)
380f82af74cSMark Johnston 		return (error);
381f82af74cSMark Johnston 	error = e820_finalize();
382f82af74cSMark Johnston 	if (error != 0)
383f82af74cSMark Johnston 		return (error);
384f82af74cSMark Johnston 
38543caa2e8SMark Johnston 	if (bootrom_boot() && strcmp(lpc_fwcfg(), "bhyve") == 0)
386f82af74cSMark Johnston 		fwctl_init();
387f82af74cSMark Johnston 
388f82af74cSMark Johnston 	if (get_config_bool("acpi_tables")) {
389f82af74cSMark Johnston 		error = acpi_build(ctx, guest_ncpus);
390f82af74cSMark Johnston 		assert(error == 0);
391f82af74cSMark Johnston 	}
392f82af74cSMark Johnston 
393f82af74cSMark Johnston 	return (0);
394f82af74cSMark Johnston }
395