1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2011 NetApp, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <assert.h>
30 #include <err.h>
31 #include <stdbool.h>
32 #include <stdlib.h>
33 
34 #include <vmmapi.h>
35 
36 #include "acpi.h"
37 #include "atkbdc.h"
38 #include "bhyverun.h"
39 #include "config.h"
40 #include "debug.h"
41 #include "e820.h"
42 #include "fwctl.h"
43 #include "ioapic.h"
44 #include "inout.h"
45 #include "kernemu_dev.h"
46 #include "mptbl.h"
47 #include "pci_irq.h"
48 #include "pci_lpc.h"
49 #include "rtc.h"
50 #include "smbiostbl.h"
51 #include "xmsr.h"
52 
53 void
54 bhyve_init_config(void)
55 {
56 	init_config();
57 
58 	/* Set default values prior to option parsing. */
59 	set_config_bool("acpi_tables", true);
60 	set_config_bool("acpi_tables_in_memory", true);
61 	set_config_value("memory.size", "256M");
62 	set_config_bool("x86.strictmsr", true);
63 	set_config_value("lpc.fwcfg", "bhyve");
64 }
65 
66 void
67 bhyve_init_vcpu(struct vcpu *vcpu)
68 {
69 	int err, tmp;
70 
71 	if (get_config_bool_default("x86.vmexit_on_hlt", false)) {
72 		err = vm_get_capability(vcpu, VM_CAP_HALT_EXIT, &tmp);
73 		if (err < 0) {
74 			EPRINTLN("VM exit on HLT not supported");
75 			exit(4);
76 		}
77 		vm_set_capability(vcpu, VM_CAP_HALT_EXIT, 1);
78 	}
79 
80 	if (get_config_bool_default("x86.vmexit_on_pause", false)) {
81 		/*
82 		 * pause exit support required for this mode
83 		 */
84 		err = vm_get_capability(vcpu, VM_CAP_PAUSE_EXIT, &tmp);
85 		if (err < 0) {
86 			EPRINTLN("SMP mux requested, no pause support");
87 			exit(4);
88 		}
89 		vm_set_capability(vcpu, VM_CAP_PAUSE_EXIT, 1);
90 	}
91 
92 	if (get_config_bool_default("x86.x2apic", false))
93 		err = vm_set_x2apic_state(vcpu, X2APIC_ENABLED);
94 	else
95 		err = vm_set_x2apic_state(vcpu, X2APIC_DISABLED);
96 
97 	if (err) {
98 		EPRINTLN("Unable to set x2apic state (%d)", err);
99 		exit(4);
100 	}
101 
102 	vm_set_capability(vcpu, VM_CAP_ENABLE_INVPCID, 1);
103 
104 	err = vm_set_capability(vcpu, VM_CAP_IPI_EXIT, 1);
105 	assert(err == 0);
106 }
107 
108 void
109 bhyve_start_vcpu(struct vcpu *vcpu, bool bsp)
110 {
111 	int error;
112 
113 	if (bsp) {
114 		if (lpc_bootrom()) {
115 			error = vm_set_capability(vcpu,
116 			    VM_CAP_UNRESTRICTED_GUEST, 1);
117 			if (error != 0) {
118 				err(4, "ROM boot failed: unrestricted guest "
119 				    "capability not available");
120 			}
121 			error = vcpu_reset(vcpu);
122 			assert(error == 0);
123 		}
124 	} else {
125 		bhyve_init_vcpu(vcpu);
126 
127 		/*
128 		 * Enable the 'unrestricted guest' mode for APs.
129 		 *
130 		 * APs startup in power-on 16-bit mode.
131 		 */
132 		error = vm_set_capability(vcpu, VM_CAP_UNRESTRICTED_GUEST, 1);
133 		assert(error == 0);
134 	}
135 
136 	fbsdrun_addcpu(vcpu_id(vcpu));
137 }
138 
139 int
140 bhyve_init_platform(struct vmctx *ctx, struct vcpu *bsp __unused)
141 {
142 	int error;
143 
144 	error = init_msr();
145 	if (error != 0)
146 		return (error);
147 	init_inout();
148 	kernemu_dev_init();
149 	atkbdc_init(ctx);
150 	pci_irq_init(ctx);
151 	ioapic_init(ctx);
152 	rtc_init(ctx);
153 	sci_init(ctx);
154 	error = e820_init(ctx);
155 	if (error != 0)
156 		return (error);
157 
158 	return (0);
159 }
160 
161 int
162 bhyve_init_platform_late(struct vmctx *ctx, struct vcpu *bsp __unused)
163 {
164 	int error;
165 
166 	if (get_config_bool_default("x86.mptable", true)) {
167 		error = mptable_build(ctx, guest_ncpus);
168 		if (error != 0)
169 			return (error);
170 	}
171 	error = smbios_build(ctx);
172 	if (error != 0)
173 		return (error);
174 	error = e820_finalize();
175 	if (error != 0)
176 		return (error);
177 
178 	if (lpc_bootrom() && strcmp(lpc_fwcfg(), "bhyve") == 0)
179 		fwctl_init();
180 
181 	if (get_config_bool("acpi_tables")) {
182 		error = acpi_build(ctx, guest_ncpus);
183 		assert(error == 0);
184 	}
185 
186 	return (0);
187 }
188