xref: /freebsd/usr.sbin/bhyve/acpi.c (revision f1d705d4f431a5553aa5e64310bdc703ba27eab4)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2012 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 /*
30  * bhyve ACPI table generator.
31  *
32  * Create the minimal set of ACPI tables required to boot FreeBSD (and
33  * hopefully other o/s's).
34  *
35  * The tables are placed in the guest's ROM area just below 1MB physical,
36  * above the MPTable.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/cpuset.h>
41 #include <sys/domainset.h>
42 #include <sys/endian.h>
43 #include <sys/errno.h>
44 #include <sys/stat.h>
45 #include <sys/tree.h>
46 
47 #include <err.h>
48 #include <paths.h>
49 #include <stdarg.h>
50 #include <stddef.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 
56 #include <dev/vmm/vmm_mem.h>
57 #include <machine/vmm.h>
58 #include <machine/vmm_dev.h>
59 #include <vmmapi.h>
60 
61 #include "bhyverun.h"
62 #include "acpi.h"
63 #include "basl.h"
64 #include "pci_emul.h"
65 #include "vmgenc.h"
66 
67 #define	BHYVE_ASL_TEMPLATE	"bhyve.XXXXXXX"
68 #define BHYVE_ASL_SUFFIX	".aml"
69 #define BHYVE_ASL_COMPILER	"/usr/sbin/iasl"
70 
71 #define BHYVE_ADDRESS_IOAPIC 	0xFEC00000
72 #define BHYVE_ADDRESS_HPET 	0xFED00000
73 #define BHYVE_ADDRESS_LAPIC 	0xFEE00000
74 
75 static int basl_keep_temps;
76 static int basl_verbose_iasl;
77 static int basl_ncpu;
78 
79 /*
80  * Contains the full pathname of the template to be passed
81  * to mkstemp/mktemps(3)
82  */
83 static char basl_template[MAXPATHLEN];
84 static char basl_stemplate[MAXPATHLEN];
85 
86 /*
87  * SRAT vCPU affinity info.
88  */
89 struct acpi_vcpu_affinity_entry {
90 	RB_ENTRY(acpi_vcpu_affinity_entry) entry;
91 	int vcpuid;
92 	int domain;
93 };
94 
95 static int vcpu_affinity_cmp(struct acpi_vcpu_affinity_entry *const a1,
96     struct acpi_vcpu_affinity_entry *const a2);
97 static RB_HEAD(vcpu_affinities,
98     acpi_vcpu_affinity_entry) aff_head = RB_INITIALIZER(&aff_head);
99 RB_GENERATE_STATIC(vcpu_affinities, acpi_vcpu_affinity_entry, entry,
100     vcpu_affinity_cmp);
101 
102 /*
103  * State for dsdt_line(), dsdt_indent(), and dsdt_unindent().
104  */
105 static FILE *dsdt_fp;
106 static int dsdt_indent_level;
107 static int dsdt_error;
108 
109 struct basl_fio {
110 	int	fd;
111 	FILE	*fp;
112 	char	f_name[MAXPATHLEN];
113 };
114 
115 #define EFPRINTF(...) \
116 	if (fprintf(__VA_ARGS__) < 0) goto err_exit
117 
118 #define EFFLUSH(x) \
119 	if (fflush(x) != 0) goto err_exit
120 
121 /*
122  * A list for additional ACPI devices like a TPM.
123  */
124 struct acpi_device_list_entry {
125 	SLIST_ENTRY(acpi_device_list_entry) chain;
126 	const struct acpi_device *dev;
127 };
128 static SLIST_HEAD(acpi_device_list,
129     acpi_device_list_entry) acpi_devices = SLIST_HEAD_INITIALIZER(acpi_devices);
130 
131 int
acpi_tables_add_device(const struct acpi_device * const dev)132 acpi_tables_add_device(const struct acpi_device *const dev)
133 {
134 	struct acpi_device_list_entry *const entry = calloc(1, sizeof(*entry));
135 	if (entry == NULL) {
136 		return (ENOMEM);
137 	}
138 
139 	entry->dev = dev;
140 	SLIST_INSERT_HEAD(&acpi_devices, entry, chain);
141 
142 	return (0);
143 }
144 
145 static int
vcpu_affinity_cmp(struct acpi_vcpu_affinity_entry * a1,struct acpi_vcpu_affinity_entry * a2)146 vcpu_affinity_cmp(struct acpi_vcpu_affinity_entry *a1,
147     struct acpi_vcpu_affinity_entry *a2)
148 {
149 	return (a1->vcpuid < a2->vcpuid ? -1 : a1->vcpuid > a2->vcpuid);
150 }
151 
152 int
acpi_add_vcpu_affinity(int vcpuid,int domain)153 acpi_add_vcpu_affinity(int vcpuid, int domain)
154 {
155 	struct acpi_vcpu_affinity_entry *entry = calloc(1, sizeof(*entry));
156 	if (entry == NULL) {
157 		return (ENOMEM);
158 	}
159 
160 	entry->vcpuid = vcpuid;
161 	entry->domain = domain;
162 	if (RB_INSERT(vcpu_affinities, &aff_head, entry) != NULL) {
163 		free(entry);
164 		return (EEXIST);
165 	}
166 
167 	return (0);
168 }
169 
170 /*
171  * Helper routines for writing to the DSDT from other modules.
172  */
173 void
dsdt_line(const char * fmt,...)174 dsdt_line(const char *fmt, ...)
175 {
176 	va_list ap;
177 
178 	if (dsdt_error != 0)
179 		return;
180 
181 	if (strcmp(fmt, "") != 0) {
182 		if (dsdt_indent_level != 0)
183 			EFPRINTF(dsdt_fp, "%*c", dsdt_indent_level * 2, ' ');
184 		va_start(ap, fmt);
185 		if (vfprintf(dsdt_fp, fmt, ap) < 0) {
186 			va_end(ap);
187 			goto err_exit;
188 		}
189 		va_end(ap);
190 	}
191 	EFPRINTF(dsdt_fp, "\n");
192 	return;
193 
194 err_exit:
195 	dsdt_error = errno;
196 }
197 
198 void
dsdt_indent(int levels)199 dsdt_indent(int levels)
200 {
201 
202 	dsdt_indent_level += levels;
203 	assert(dsdt_indent_level >= 0);
204 }
205 
206 void
dsdt_unindent(int levels)207 dsdt_unindent(int levels)
208 {
209 
210 	assert(dsdt_indent_level >= levels);
211 	dsdt_indent_level -= levels;
212 }
213 
214 void
dsdt_fixed_ioport(uint16_t iobase,uint16_t length)215 dsdt_fixed_ioport(uint16_t iobase, uint16_t length)
216 {
217 
218 	dsdt_line("IO (Decode16,");
219 	dsdt_line("  0x%04X,             // Range Minimum", iobase);
220 	dsdt_line("  0x%04X,             // Range Maximum", iobase);
221 	dsdt_line("  0x01,               // Alignment");
222 	dsdt_line("  0x%02X,               // Length", length);
223 	dsdt_line("  )");
224 }
225 
226 void
dsdt_fixed_irq(uint8_t irq)227 dsdt_fixed_irq(uint8_t irq)
228 {
229 
230 	dsdt_line("IRQNoFlags ()");
231 	dsdt_line("  {%d}", irq);
232 }
233 
234 void
dsdt_fixed_mem32(uint32_t base,uint32_t length)235 dsdt_fixed_mem32(uint32_t base, uint32_t length)
236 {
237 
238 	dsdt_line("Memory32Fixed (ReadWrite,");
239 	dsdt_line("  0x%08X,         // Address Base", base);
240 	dsdt_line("  0x%08X,         // Address Length", length);
241 	dsdt_line("  )");
242 }
243 
244 static int
basl_fwrite_dsdt(FILE * fp)245 basl_fwrite_dsdt(FILE *fp)
246 {
247 	dsdt_fp = fp;
248 	dsdt_error = 0;
249 	dsdt_indent_level = 0;
250 
251 	dsdt_line("/*");
252 	dsdt_line(" * bhyve DSDT template");
253 	dsdt_line(" */");
254 	dsdt_line("DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2,"
255 		 "\"BHYVE \", \"BVDSDT  \", 0x00000001)");
256 	dsdt_line("{");
257 	dsdt_line("  Name (_S5, Package ()");
258 	dsdt_line("  {");
259 	dsdt_line("      0x05,");
260 	dsdt_line("      Zero,");
261 	dsdt_line("  })");
262 
263 	pci_write_dsdt();
264 
265 #ifdef __amd64__
266 	dsdt_line("");
267 	dsdt_line("  Scope (_SB.PC00)");
268 	dsdt_line("  {");
269 	dsdt_line("    Device (HPET)");
270 	dsdt_line("    {");
271 	dsdt_line("      Name (_HID, EISAID(\"PNP0103\"))");
272 	dsdt_line("      Name (_UID, 0)");
273 	dsdt_line("      Name (_CRS, ResourceTemplate ()");
274 	dsdt_line("      {");
275 	dsdt_indent(4);
276 	dsdt_fixed_mem32(0xFED00000, 0x400);
277 	dsdt_unindent(4);
278 	dsdt_line("      })");
279 	dsdt_line("    }");
280 	dsdt_line("  }");
281 #endif
282 
283 	vmgenc_write_dsdt();
284 
285 	const struct acpi_device_list_entry *entry;
286 	SLIST_FOREACH(entry, &acpi_devices, chain) {
287 		BASL_EXEC(acpi_device_write_dsdt(entry->dev));
288 	}
289 
290 	dsdt_line("}");
291 
292 	if (dsdt_error != 0)
293 		return (dsdt_error);
294 
295 	EFFLUSH(fp);
296 
297 	return (0);
298 
299 err_exit:
300 	return (errno);
301 }
302 
303 static int
basl_open(struct basl_fio * bf,int suffix)304 basl_open(struct basl_fio *bf, int suffix)
305 {
306 	int err;
307 
308 	err = 0;
309 
310 	if (suffix) {
311 		strlcpy(bf->f_name, basl_stemplate, MAXPATHLEN);
312 		bf->fd = mkstemps(bf->f_name, strlen(BHYVE_ASL_SUFFIX));
313 	} else {
314 		strlcpy(bf->f_name, basl_template, MAXPATHLEN);
315 		bf->fd = mkstemp(bf->f_name);
316 	}
317 
318 	if (bf->fd > 0) {
319 		bf->fp = fdopen(bf->fd, "w+");
320 		if (bf->fp == NULL) {
321 			unlink(bf->f_name);
322 			close(bf->fd);
323 		}
324 	} else {
325 		err = 1;
326 	}
327 
328 	return (err);
329 }
330 
331 static void
basl_close(struct basl_fio * bf)332 basl_close(struct basl_fio *bf)
333 {
334 
335 	if (!basl_keep_temps)
336 		unlink(bf->f_name);
337 	fclose(bf->fp);
338 }
339 
340 static int
basl_start(struct basl_fio * in,struct basl_fio * out)341 basl_start(struct basl_fio *in, struct basl_fio *out)
342 {
343 	int err;
344 
345 	err = basl_open(in, 0);
346 	if (!err) {
347 		err = basl_open(out, 1);
348 		if (err) {
349 			basl_close(in);
350 		}
351 	}
352 
353 	return (err);
354 }
355 
356 static void
basl_end(struct basl_fio * in,struct basl_fio * out)357 basl_end(struct basl_fio *in, struct basl_fio *out)
358 {
359 
360 	basl_close(in);
361 	basl_close(out);
362 }
363 
364 static int
basl_load(struct vmctx * ctx,int fd)365 basl_load(struct vmctx *ctx, int fd)
366 {
367 	struct stat sb;
368 	void *addr;
369 
370 	if (fstat(fd, &sb) < 0)
371 		return (errno);
372 
373 	addr = calloc(1, sb.st_size);
374 	if (addr == NULL)
375 		return (ENOMEM);
376 
377 	if (read(fd, addr, sb.st_size) < 0)
378 		return (errno);
379 
380 	struct basl_table *table;
381 
382 	uint8_t name[ACPI_NAMESEG_SIZE + 1] = { 0 };
383 	memcpy(name, addr, sizeof(name) - 1 /* last char is '\0' */);
384 	BASL_EXEC(basl_table_create(&table, ctx, name, BASL_TABLE_ALIGNMENT));
385 	BASL_EXEC(basl_table_append_bytes(table, addr, sb.st_size));
386 
387 	free(addr);
388 	return (0);
389 }
390 
391 static int
basl_compile(struct vmctx * ctx,int (* fwrite_section)(FILE *))392 basl_compile(struct vmctx *ctx, int (*fwrite_section)(FILE *))
393 {
394 	struct basl_fio io[2];
395 	static char iaslbuf[3*MAXPATHLEN + 10];
396 	const char *fmt;
397 	int err;
398 
399 	err = basl_start(&io[0], &io[1]);
400 	if (!err) {
401 		err = (*fwrite_section)(io[0].fp);
402 
403 		if (!err) {
404 			/*
405 			 * iasl sends the results of the compilation to
406 			 * stdout. Shut this down by using the shell to
407 			 * redirect stdout to /dev/null, unless the user
408 			 * has requested verbose output for debugging
409 			 * purposes
410 			 */
411 			fmt = basl_verbose_iasl ?
412 				"%s -p %s %s" :
413 				"/bin/sh -c \"%s -p %s %s\" 1> /dev/null";
414 
415 			snprintf(iaslbuf, sizeof(iaslbuf),
416 				 fmt,
417 				 BHYVE_ASL_COMPILER,
418 				 io[1].f_name, io[0].f_name);
419 			err = system(iaslbuf);
420 
421 			if (!err) {
422 				/*
423 				 * Copy the aml output file into guest
424 				 * memory at the specified location
425 				 */
426 				err = basl_load(ctx, io[1].fd);
427 			}
428 		}
429 		basl_end(&io[0], &io[1]);
430 	}
431 
432 	return (err);
433 }
434 
435 static int
basl_make_templates(void)436 basl_make_templates(void)
437 {
438 	const char *tmpdir;
439 	int err;
440 	int len;
441 
442 	err = 0;
443 
444 	/*
445 	 *
446 	 */
447 	if ((tmpdir = getenv("BHYVE_TMPDIR")) == NULL || *tmpdir == '\0' ||
448 	    (tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') {
449 		tmpdir = _PATH_TMP;
450 	}
451 
452 	len = strlen(tmpdir);
453 
454 	if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1) < MAXPATHLEN) {
455 		strcpy(basl_template, tmpdir);
456 		while (len > 0 && basl_template[len - 1] == '/')
457 			len--;
458 		basl_template[len] = '/';
459 		strcpy(&basl_template[len + 1], BHYVE_ASL_TEMPLATE);
460 	} else
461 		err = E2BIG;
462 
463 	if (!err) {
464 		/*
465 		 * len has been initialized (and maybe adjusted) above
466 		 */
467 		if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1 +
468 		     sizeof(BHYVE_ASL_SUFFIX)) < MAXPATHLEN) {
469 			strcpy(basl_stemplate, tmpdir);
470 			basl_stemplate[len] = '/';
471 			strcpy(&basl_stemplate[len + 1], BHYVE_ASL_TEMPLATE);
472 			len = strlen(basl_stemplate);
473 			strcpy(&basl_stemplate[len], BHYVE_ASL_SUFFIX);
474 		} else
475 			err = E2BIG;
476 	}
477 
478 	return (err);
479 }
480 
481 static int
build_dsdt(struct vmctx * const ctx)482 build_dsdt(struct vmctx *const ctx)
483 {
484 	BASL_EXEC(basl_compile(ctx, basl_fwrite_dsdt));
485 
486 	return (0);
487 }
488 
489 static int
build_facs(struct vmctx * const ctx)490 build_facs(struct vmctx *const ctx)
491 {
492 	ACPI_TABLE_FACS facs;
493 	struct basl_table *table;
494 
495 	BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_FACS,
496 	    BASL_TABLE_ALIGNMENT_FACS));
497 
498 	memset(&facs, 0, sizeof(facs));
499 	memcpy(facs.Signature, ACPI_SIG_FACS, ACPI_NAMESEG_SIZE);
500 	facs.Length = sizeof(facs);
501 	facs.Version = htole32(2);
502 	BASL_EXEC(basl_table_append_bytes(table, &facs, sizeof(facs)));
503 
504 	return (0);
505 }
506 
507 static int
build_fadt(struct vmctx * const ctx)508 build_fadt(struct vmctx *const ctx)
509 {
510 	ACPI_TABLE_FADT fadt;
511 	struct basl_table *table;
512 
513 	BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_FADT,
514 	    BASL_TABLE_ALIGNMENT));
515 
516 	memset(&fadt, 0, sizeof(fadt));
517 	BASL_EXEC(basl_table_append_header(table, ACPI_SIG_FADT, 5, 1));
518 	fadt.Facs = htole32(0); /* patched by basl */
519 	fadt.Dsdt = htole32(0); /* patched by basl */
520 	fadt.SciInterrupt = htole16(SCI_INT);
521 	fadt.SmiCommand = htole32(SMI_CMD);
522 	fadt.AcpiEnable = BHYVE_ACPI_ENABLE;
523 	fadt.AcpiDisable = BHYVE_ACPI_DISABLE;
524 	fadt.Pm1aEventBlock = htole32(PM1A_EVT_ADDR);
525 	fadt.Pm1aControlBlock = htole32(PM1A_CNT_ADDR);
526 	fadt.PmTimerBlock = htole32(IO_PMTMR);
527 	fadt.Gpe0Block = htole32(IO_GPE0_BLK);
528 	fadt.Pm1EventLength = 4;
529 	fadt.Pm1ControlLength = 2;
530 	fadt.PmTimerLength = 4;
531 	fadt.Gpe0BlockLength = IO_GPE0_LEN;
532 	fadt.Century = 0x32;
533 	fadt.BootFlags = htole16(ACPI_FADT_NO_VGA | ACPI_FADT_NO_ASPM);
534 	fadt.Flags = htole32(ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
535 	    ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_32BIT_TIMER |
536 	    ACPI_FADT_RESET_REGISTER | ACPI_FADT_HEADLESS |
537 	    ACPI_FADT_APIC_PHYSICAL);
538 	basl_fill_gas(&fadt.ResetRegister, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
539 	    ACPI_GAS_ACCESS_WIDTH_BYTE, 0xCF9);
540 	fadt.ResetValue = 6;
541 	fadt.MinorRevision = 1;
542 	fadt.XFacs = htole64(0); /* patched by basl */
543 	fadt.XDsdt = htole64(0); /* patched by basl */
544 	basl_fill_gas(&fadt.XPm1aEventBlock, ACPI_ADR_SPACE_SYSTEM_IO, 0x20, 0,
545 	    ACPI_GAS_ACCESS_WIDTH_WORD, PM1A_EVT_ADDR);
546 	basl_fill_gas(&fadt.XPm1bEventBlock, ACPI_ADR_SPACE_SYSTEM_IO, 0, 0,
547 	    ACPI_GAS_ACCESS_WIDTH_UNDEFINED, 0);
548 	basl_fill_gas(&fadt.XPm1aControlBlock, ACPI_ADR_SPACE_SYSTEM_IO, 0x10,
549 	    0, ACPI_GAS_ACCESS_WIDTH_WORD, PM1A_CNT_ADDR);
550 	basl_fill_gas(&fadt.XPm1bControlBlock, ACPI_ADR_SPACE_SYSTEM_IO, 0, 0,
551 	    ACPI_GAS_ACCESS_WIDTH_UNDEFINED, 0);
552 	basl_fill_gas(&fadt.XPm2ControlBlock, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
553 	    ACPI_GAS_ACCESS_WIDTH_UNDEFINED, 0);
554 	basl_fill_gas(&fadt.XPmTimerBlock, ACPI_ADR_SPACE_SYSTEM_IO, 0x20, 0,
555 	    ACPI_GAS_ACCESS_WIDTH_DWORD, IO_PMTMR);
556 	basl_fill_gas(&fadt.XGpe0Block, ACPI_ADR_SPACE_SYSTEM_IO,
557 	    IO_GPE0_LEN * 8, 0, ACPI_GAS_ACCESS_WIDTH_BYTE, IO_GPE0_BLK);
558 	basl_fill_gas(&fadt.XGpe1Block, ACPI_ADR_SPACE_SYSTEM_IO, 0, 0,
559 	    ACPI_GAS_ACCESS_WIDTH_UNDEFINED, 0);
560 	basl_fill_gas(&fadt.SleepControl, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
561 	    ACPI_GAS_ACCESS_WIDTH_BYTE, 0);
562 	basl_fill_gas(&fadt.SleepStatus, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
563 	    ACPI_GAS_ACCESS_WIDTH_BYTE, 0);
564 	BASL_EXEC(basl_table_append_content(table, &fadt, sizeof(fadt)));
565 
566 	BASL_EXEC(basl_table_add_pointer(table, ACPI_SIG_FACS,
567 	    offsetof(ACPI_TABLE_FADT, Facs), sizeof(fadt.Facs)));
568 	BASL_EXEC(basl_table_add_pointer(table, ACPI_SIG_DSDT,
569 	    offsetof(ACPI_TABLE_FADT, Dsdt), sizeof(fadt.Dsdt)));
570 	BASL_EXEC(basl_table_add_pointer(table, ACPI_SIG_FACS,
571 	    offsetof(ACPI_TABLE_FADT, XFacs), sizeof(fadt.XFacs)));
572 	BASL_EXEC(basl_table_add_pointer(table, ACPI_SIG_DSDT,
573 	    offsetof(ACPI_TABLE_FADT, XDsdt), sizeof(fadt.XDsdt)));
574 
575 	BASL_EXEC(basl_table_register_to_rsdt(table));
576 
577 	return (0);
578 }
579 
580 #ifdef __amd64__
581 static int
build_hpet(struct vmctx * const ctx)582 build_hpet(struct vmctx *const ctx)
583 {
584 	ACPI_TABLE_HPET hpet;
585 	struct basl_table *table;
586 	uint32_t hpet_capabilities;
587 	int err;
588 
589 	err = vm_get_hpet_capabilities(ctx, &hpet_capabilities);
590 	if (err != 0)
591 		return (err);
592 
593 	BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_HPET,
594 	    BASL_TABLE_ALIGNMENT));
595 
596 	memset(&hpet, 0, sizeof(hpet));
597 	BASL_EXEC(basl_table_append_header(table, ACPI_SIG_HPET, 1, 1));
598 	hpet.Id = htole32(hpet_capabilities);
599 	basl_fill_gas(&hpet.Address, ACPI_ADR_SPACE_SYSTEM_MEMORY, 0, 0,
600 	    ACPI_GAS_ACCESS_WIDTH_LEGACY, BHYVE_ADDRESS_HPET);
601 	hpet.Flags = ACPI_HPET_PAGE_PROTECT4;
602 	BASL_EXEC(basl_table_append_content(table, &hpet, sizeof(hpet)));
603 
604 	BASL_EXEC(basl_table_register_to_rsdt(table));
605 
606 	return (0);
607 }
608 #endif
609 
610 static int
build_madt(struct vmctx * const ctx)611 build_madt(struct vmctx *const ctx)
612 {
613 	ACPI_TABLE_MADT madt;
614 	ACPI_MADT_LOCAL_APIC madt_lapic;
615 	ACPI_MADT_IO_APIC madt_ioapic;
616 	ACPI_MADT_INTERRUPT_OVERRIDE madt_irq_override;
617 	ACPI_MADT_LOCAL_APIC_NMI madt_lapic_nmi;
618 	struct basl_table *table;
619 
620 	BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_MADT,
621 	    BASL_TABLE_ALIGNMENT));
622 
623 	memset(&madt, 0, sizeof(madt));
624 	BASL_EXEC(basl_table_append_header(table, ACPI_SIG_MADT, 1, 1));
625 	madt.Address = htole32(BHYVE_ADDRESS_LAPIC);
626 	madt.Flags = htole32(ACPI_MADT_PCAT_COMPAT);
627 	BASL_EXEC(basl_table_append_content(table, &madt, sizeof(madt)));
628 
629 	/* Local APIC for each CPU */
630 	for (int i = 0; i < basl_ncpu; ++i) {
631 		memset(&madt_lapic, 0, sizeof(madt_lapic));
632 		madt_lapic.Header.Type = ACPI_MADT_TYPE_LOCAL_APIC;
633 		madt_lapic.Header.Length = sizeof(madt_lapic);
634 		madt_lapic.ProcessorId = i;
635 		madt_lapic.Id = i;
636 		madt_lapic.LapicFlags = htole32(ACPI_MADT_ENABLED);
637 		BASL_EXEC(basl_table_append_bytes(table, &madt_lapic,
638 		    sizeof(madt_lapic)));
639 	}
640 
641 	/* I/O APIC */
642 	memset(&madt_ioapic, 0, sizeof(madt_ioapic));
643 	madt_ioapic.Header.Type = ACPI_MADT_TYPE_IO_APIC;
644 	madt_ioapic.Header.Length = sizeof(madt_ioapic);
645 	madt_ioapic.Address = htole32(BHYVE_ADDRESS_IOAPIC);
646 	BASL_EXEC(
647 	    basl_table_append_bytes(table, &madt_ioapic, sizeof(madt_ioapic)));
648 
649 	/* Legacy IRQ0 is connected to pin 2 of the I/O APIC */
650 	memset(&madt_irq_override, 0, sizeof(madt_irq_override));
651 	madt_irq_override.Header.Type = ACPI_MADT_TYPE_INTERRUPT_OVERRIDE;
652 	madt_irq_override.Header.Length = sizeof(madt_irq_override);
653 	madt_irq_override.GlobalIrq = htole32(2);
654 	madt_irq_override.IntiFlags = htole16(
655 	    ACPI_MADT_POLARITY_ACTIVE_HIGH | ACPI_MADT_TRIGGER_EDGE);
656 	BASL_EXEC(basl_table_append_bytes(table, &madt_irq_override,
657 	    sizeof(madt_irq_override)));
658 
659 	memset(&madt_irq_override, 0, sizeof(madt_irq_override));
660 	madt_irq_override.Header.Type = ACPI_MADT_TYPE_INTERRUPT_OVERRIDE;
661 	madt_irq_override.Header.Length = sizeof(madt_irq_override);
662 	madt_irq_override.SourceIrq = SCI_INT;
663 	madt_irq_override.GlobalIrq = htole32(SCI_INT);
664 	madt_irq_override.IntiFlags = htole16(
665 	    ACPI_MADT_POLARITY_ACTIVE_LOW | ACPI_MADT_TRIGGER_LEVEL);
666 	BASL_EXEC(basl_table_append_bytes(table, &madt_irq_override,
667 	    sizeof(madt_irq_override)));
668 
669 	/* Local APIC NMI is conntected to LINT 1 on all CPUs */
670 	memset(&madt_lapic_nmi, 0, sizeof(madt_lapic_nmi));
671 	madt_lapic_nmi.Header.Type = ACPI_MADT_TYPE_LOCAL_APIC_NMI;
672 	madt_lapic_nmi.Header.Length = sizeof(madt_lapic_nmi);
673 	madt_lapic_nmi.ProcessorId = 0xFF;
674 	madt_lapic_nmi.IntiFlags = htole16(
675 	    ACPI_MADT_POLARITY_ACTIVE_HIGH | ACPI_MADT_TRIGGER_EDGE);
676 	madt_lapic_nmi.Lint = 1;
677 	BASL_EXEC(basl_table_append_bytes(table, &madt_lapic_nmi,
678 	    sizeof(madt_lapic_nmi)));
679 
680 	BASL_EXEC(basl_table_register_to_rsdt(table));
681 
682 	return (0);
683 }
684 
685 static int
build_mcfg(struct vmctx * const ctx)686 build_mcfg(struct vmctx *const ctx)
687 {
688 	ACPI_TABLE_MCFG mcfg;
689 	ACPI_MCFG_ALLOCATION mcfg_allocation;
690 	struct basl_table *table;
691 
692 	BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_MCFG,
693 	    BASL_TABLE_ALIGNMENT));
694 
695 	memset(&mcfg, 0, sizeof(mcfg));
696 	BASL_EXEC(basl_table_append_header(table, ACPI_SIG_MCFG, 1, 1));
697 	BASL_EXEC(basl_table_append_content(table, &mcfg, sizeof(mcfg)));
698 
699 	memset(&mcfg_allocation, 0, sizeof(mcfg_allocation));
700 	mcfg_allocation.Address = htole64(pci_ecfg_base());
701 	mcfg_allocation.EndBusNumber = 0xFF;
702 	BASL_EXEC(basl_table_append_bytes(table, &mcfg_allocation,
703 	    sizeof(mcfg_allocation)));
704 
705 	BASL_EXEC(basl_table_register_to_rsdt(table));
706 
707 	return (0);
708 }
709 
710 static int
build_rsdp(struct vmctx * const ctx)711 build_rsdp(struct vmctx *const ctx)
712 {
713 	ACPI_TABLE_RSDP rsdp;
714 	struct basl_table *table;
715 
716 	BASL_EXEC(basl_table_create(&table, ctx, ACPI_RSDP_NAME,
717 	    BASL_TABLE_ALIGNMENT));
718 
719 	memset(&rsdp, 0, sizeof(rsdp));
720 	memcpy(rsdp.Signature, ACPI_SIG_RSDP, 8);
721 	rsdp.Checksum = 0; /* patched by basl */
722 	memcpy(rsdp.OemId, "BHYVE ", ACPI_OEM_ID_SIZE);
723 	rsdp.Revision = 2;
724 	rsdp.RsdtPhysicalAddress = htole32(0); /* patched by basl */
725 	rsdp.Length = htole32(0);	       /* patched by basl */
726 	rsdp.XsdtPhysicalAddress = htole64(0); /* patched by basl */
727 	rsdp.ExtendedChecksum = 0;	       /* patched by basl */
728 	BASL_EXEC(basl_table_append_bytes(table, &rsdp, sizeof(rsdp)));
729 
730 	BASL_EXEC(basl_table_add_checksum(table,
731 	    offsetof(ACPI_TABLE_RSDP, Checksum), 0, 20));
732 	BASL_EXEC(basl_table_add_pointer(table, ACPI_SIG_RSDT,
733 	    offsetof(ACPI_TABLE_RSDP, RsdtPhysicalAddress),
734 	    sizeof(rsdp.RsdtPhysicalAddress)));
735 	BASL_EXEC(basl_table_add_length(table,
736 	    offsetof(ACPI_TABLE_RSDP, Length), sizeof(rsdp.Length)));
737 	BASL_EXEC(basl_table_add_pointer(table, ACPI_SIG_XSDT,
738 	    offsetof(ACPI_TABLE_RSDP, XsdtPhysicalAddress),
739 	    sizeof(rsdp.XsdtPhysicalAddress)));
740 	BASL_EXEC(basl_table_add_checksum(table,
741 	    offsetof(ACPI_TABLE_RSDP, ExtendedChecksum), 0,
742 	    BASL_TABLE_CHECKSUM_LEN_FULL_TABLE));
743 
744 	return (0);
745 }
746 
747 static int
build_spcr(struct vmctx * const ctx)748 build_spcr(struct vmctx *const ctx)
749 {
750 	ACPI_TABLE_SPCR spcr;
751 	struct basl_table *table;
752 
753 	BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_SPCR,
754 	    BASL_TABLE_ALIGNMENT));
755 
756 	memset(&spcr, 0, sizeof(spcr));
757 	BASL_EXEC(basl_table_append_header(table, ACPI_SIG_SPCR, 1, 1));
758 	spcr.InterfaceType = ACPI_DBG2_16550_COMPATIBLE;
759 	basl_fill_gas(&spcr.SerialPort, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
760 	    ACPI_GAS_ACCESS_WIDTH_LEGACY, 0x3F8);
761 	spcr.InterruptType = ACPI_SPCR_INTERRUPT_TYPE_8259;
762 	spcr.PcInterrupt = 4;
763 	spcr.BaudRate = ACPI_SPCR_BAUD_RATE_115200;
764 	spcr.Parity = ACPI_SPCR_PARITY_NO_PARITY;
765 	spcr.StopBits = ACPI_SPCR_STOP_BITS_1;
766 	spcr.FlowControl = 3; /* RTS/CTS | DCD */
767 	spcr.TerminalType = ACPI_SPCR_TERMINAL_TYPE_VT_UTF8;
768 	BASL_EXEC(basl_table_append_content(table, &spcr, sizeof(spcr)));
769 
770 	BASL_EXEC(basl_table_register_to_rsdt(table));
771 
772 	return (0);
773 }
774 
775 static int
build_srat(struct vmctx * const ctx)776 build_srat(struct vmctx *const ctx)
777 {
778 	ACPI_TABLE_SRAT srat;
779 	ACPI_SRAT_MEM_AFFINITY srat_mem_affinity;
780 	ACPI_SRAT_CPU_AFFINITY srat_cpu_affinity;
781 
782 	struct acpi_vcpu_affinity_entry *ep;
783 	struct basl_table *table;
784 	int segid, domain;
785 	int _flags, _prot;
786 	vm_ooffset_t _off;
787 	size_t maplen;
788 	uint64_t gpa;
789 	int ret;
790 
791 	if (RB_EMPTY(&aff_head))
792 		return (0);
793 
794 	memset(&srat, 0, sizeof(srat));
795 	BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_SRAT,
796 	    BASL_TABLE_ALIGNMENT));
797 	BASL_EXEC(basl_table_append_header(table, ACPI_SIG_SRAT, 1, 1));
798 	srat.TableRevision = 1;
799 	BASL_EXEC(basl_table_append_content(table, &srat, sizeof(srat)));
800 
801 	/*
802 	 * Iterate over the VM's memory maps and add
803 	 * a 'Memory Affinity Structure' for each mapping.
804 	 */
805 	gpa = 0;
806 	while (1) {
807 		ret = vm_mmap_getnext(ctx, &gpa, &segid, &_off, &maplen, &_prot,
808 		    &_flags);
809 		if (ret) {
810 			break;
811 		}
812 
813 		if (segid >= VM_SYSMEM && segid < VM_BOOTROM) {
814 			domain = segid - VM_SYSMEM;
815 		} else {
816 			/* Treat devmem segs as domain 0. */
817 			domain = 0;
818 		}
819 		memset(&srat_mem_affinity, 0, sizeof(srat_mem_affinity));
820 		srat_mem_affinity.Header.Type = ACPI_SRAT_TYPE_MEMORY_AFFINITY;
821 		srat_mem_affinity.Header.Length = sizeof(srat_mem_affinity);
822 		srat_mem_affinity.Flags |= ACPI_SRAT_MEM_ENABLED;
823 		srat_mem_affinity.ProximityDomain = htole32(domain);
824 		srat_mem_affinity.BaseAddress = htole64(gpa);
825 		srat_mem_affinity.Length = htole64(maplen);
826 		srat_mem_affinity.Flags = htole32(ACPI_SRAT_MEM_ENABLED);
827 		BASL_EXEC(basl_table_append_bytes(table, &srat_mem_affinity,
828 		    sizeof(srat_mem_affinity)));
829 		gpa += maplen;
830 	}
831 
832 	/*
833 	 * Iterate over each "vCPUid to domain id" mapping and emit a
834 	 * 'Processor Local APIC/SAPIC Affinity Structure' for each entry.
835 	 */
836 	RB_FOREACH(ep, vcpu_affinities, &aff_head) {
837 		memset(&srat_cpu_affinity, 0, sizeof(srat_cpu_affinity));
838 		srat_cpu_affinity.Header.Type = ACPI_SRAT_TYPE_CPU_AFFINITY;
839 		srat_cpu_affinity.Header.Length = sizeof(srat_cpu_affinity);
840 		srat_cpu_affinity.ProximityDomainLo = (uint8_t)ep->domain;
841 		srat_cpu_affinity.ApicId = (uint8_t)ep->vcpuid;
842 		srat_cpu_affinity.Flags = htole32(ACPI_SRAT_CPU_USE_AFFINITY);
843 		BASL_EXEC(basl_table_append_bytes(table, &srat_cpu_affinity,
844 		    sizeof(srat_cpu_affinity)));
845 	}
846 
847 	BASL_EXEC(basl_table_register_to_rsdt(table));
848 
849 	return (0);
850 }
851 
852 int
acpi_build(struct vmctx * ctx,int ncpu)853 acpi_build(struct vmctx *ctx, int ncpu)
854 {
855 	basl_ncpu = ncpu;
856 
857 	/*
858 	 * For debug, allow the user to have iasl compiler output sent
859 	 * to stdout rather than /dev/null
860 	 */
861 	if (getenv("BHYVE_ACPI_VERBOSE_IASL"))
862 		basl_verbose_iasl = 1;
863 
864 	/*
865 	 * Allow the user to keep the generated ASL files for debugging
866 	 * instead of deleting them following use
867 	 */
868 	if (getenv("BHYVE_ACPI_KEEPTMPS"))
869 		basl_keep_temps = 1;
870 
871 	BASL_EXEC(basl_init(ctx));
872 
873 	BASL_EXEC(basl_make_templates());
874 
875 	/*
876 	 * Generate ACPI tables and copy them into guest memory.
877 	 *
878 	 * According to UEFI Specification v6.3 chapter 5.1 the FADT should be
879 	 * the first table pointed to by XSDT. For that reason, build it as the
880 	 * first table after XSDT.
881 	 */
882 	BASL_EXEC(build_rsdp(ctx));
883 	BASL_EXEC(build_fadt(ctx));
884 	BASL_EXEC(build_madt(ctx));
885 #ifdef __amd64__
886 	BASL_EXEC(build_hpet(ctx));
887 #endif
888 	BASL_EXEC(build_mcfg(ctx));
889 	BASL_EXEC(build_facs(ctx));
890 	BASL_EXEC(build_spcr(ctx));
891 	BASL_EXEC(build_srat(ctx));
892 
893 	/* Build ACPI device-specific tables such as a TPM2 table. */
894 	const struct acpi_device_list_entry *entry;
895 	SLIST_FOREACH(entry, &acpi_devices, chain) {
896 		BASL_EXEC(acpi_device_build_table(entry->dev));
897 	}
898 
899 	BASL_EXEC(build_dsdt(ctx));
900 
901 	BASL_EXEC(basl_finish());
902 
903 	return (0);
904 }
905