Page MenuHomeFreeBSD

D36991.diff
No OneTemporary

D36991.diff

diff --git a/usr.sbin/bhyve/basl.h b/usr.sbin/bhyve/basl.h
--- a/usr.sbin/bhyve/basl.h
+++ b/usr.sbin/bhyve/basl.h
@@ -48,5 +48,7 @@
uint64_t address);
int basl_table_append_int(struct basl_table *table, uint64_t val, uint8_t size);
int basl_table_append_length(struct basl_table *table, uint8_t size);
+int basl_table_append_pointer(struct basl_table *table,
+ const uint8_t src_signature[ACPI_NAMESEG_SIZE], uint8_t size);
int basl_table_create(struct basl_table **table, struct vmctx *ctx,
const uint8_t *name, uint32_t alignment, uint32_t off);
diff --git a/usr.sbin/bhyve/basl.c b/usr.sbin/bhyve/basl.c
--- a/usr.sbin/bhyve/basl.c
+++ b/usr.sbin/bhyve/basl.c
@@ -34,6 +34,13 @@
uint8_t size;
};
+struct basl_table_pointer {
+ STAILQ_ENTRY(basl_table_pointer) chain;
+ uint8_t src_signature[ACPI_NAMESEG_SIZE];
+ uint32_t off;
+ uint8_t size;
+};
+
struct basl_table {
STAILQ_ENTRY(basl_table) chain;
struct vmctx *ctx;
@@ -45,10 +52,30 @@
STAILQ_HEAD(basl_table_checksum_list,
basl_table_checksum) checksums;
STAILQ_HEAD(basl_table_length_list, basl_table_length) lengths;
+ STAILQ_HEAD(basl_table_pointer_list, basl_table_pointer) pointers;
};
static STAILQ_HEAD(basl_table_list, basl_table) basl_tables = STAILQ_HEAD_INITIALIZER(
basl_tables);
+static __inline uint64_t
+basl_le_dec(void *pp, size_t len)
+{
+ assert(len <= 8);
+
+ switch (len) {
+ case 1:
+ return ((uint8_t *)pp)[0];
+ case 2:
+ return le16dec(pp);
+ case 4:
+ return le32dec(pp);
+ case 8:
+ return le64dec(pp);
+ }
+
+ return 0;
+}
+
static __inline void
basl_le_enc(void *pp, uint64_t val, size_t len)
{
@@ -176,6 +203,73 @@
return (0);
}
+static struct basl_table *
+basl_get_table_by_signature(const uint8_t signature[ACPI_NAMESEG_SIZE])
+{
+ struct basl_table *table;
+
+ STAILQ_FOREACH(table, &basl_tables, chain) {
+ const ACPI_TABLE_HEADER *const header =
+ (const ACPI_TABLE_HEADER *)table->data;
+
+ if (strncmp(header->Signature, signature,
+ sizeof(header->Signature)) == 0) {
+ return (table);
+ }
+ }
+
+ warnx("%s: %.4s not found", __func__, signature);
+ return (NULL);
+}
+
+static int
+basl_finish_patch_pointers(struct basl_table *const table)
+{
+ struct basl_table_pointer *pointer;
+
+ STAILQ_FOREACH(pointer, &table->pointers, chain) {
+ const struct basl_table *src_table;
+ uint8_t *gva;
+ uint64_t gpa, val;
+
+ assert(pointer->off < table->len);
+ assert(pointer->off + pointer->size <= table->len);
+
+ src_table = basl_get_table_by_signature(pointer->src_signature);
+ if (src_table == NULL) {
+ warnx("%s: could not find ACPI table %.4s", __func__,
+ pointer->src_signature);
+ return (EFAULT);
+ }
+
+ /*
+ * Install ACPI tables directly in guest memory for use by
+ * guests which do not boot via EFI. EFI ROMs provide a pointer
+ * to the firmware generated ACPI tables instead, but it doesn't
+ * hurt to install the tables always.
+ */
+ gpa = BHYVE_ACPI_BASE + table->off;
+ if (gpa < BHYVE_ACPI_BASE) {
+ warnx("%s: table offset of 0x%8x is too large",
+ __func__, table->off);
+ return (EFAULT);
+ }
+
+ gva = vm_map_gpa(table->ctx, gpa, table->len);
+ if (gva == NULL) {
+ warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]",
+ __func__, gpa, gpa + table->len);
+ return (ENOMEM);
+ }
+
+ val = basl_le_dec(gva + pointer->off, pointer->size);
+ val += BHYVE_ACPI_BASE + src_table->off;
+ basl_le_enc(gva + pointer->off, val, pointer->size);
+ }
+
+ return (0);
+}
+
static int
basl_finish_set_length(struct basl_table *const table)
{
@@ -212,6 +306,8 @@
BASL_EXEC(basl_finish_install_guest_tables(table));
}
STAILQ_FOREACH(table, &basl_tables, chain) {
+ BASL_EXEC(basl_finish_patch_pointers(table));
+
/*
* Calculate the checksum as last step!
*/
@@ -268,6 +364,29 @@
return (0);
}
+static int
+basl_table_add_pointer(struct basl_table *const table,
+ const uint8_t src_signature[ACPI_NAMESEG_SIZE], const uint32_t off,
+ const uint8_t size)
+{
+ struct basl_table_pointer *pointer;
+
+ pointer = calloc(1, sizeof(struct basl_table_pointer));
+ if (pointer == NULL) {
+ warnx("%s: failed to allocate pointer", __func__);
+ return (ENOMEM);
+ }
+
+ memcpy(pointer->src_signature, src_signature,
+ sizeof(pointer->src_signature));
+ pointer->off = off;
+ pointer->size = size;
+
+ STAILQ_INSERT_TAIL(&table->pointers, pointer, chain);
+
+ return (0);
+}
+
int
basl_table_append_bytes(struct basl_table *const table, const void *const bytes,
const uint32_t len)
@@ -351,6 +470,19 @@
return (0);
}
+int
+basl_table_append_pointer(struct basl_table *const table,
+ const uint8_t src_signature[ACPI_NAMESEG_SIZE], const uint8_t size)
+{
+ assert(table != NULL);
+ assert(size == 4 || size == 8);
+
+ BASL_EXEC(basl_table_add_pointer(table, src_signature, table->len, size));
+ BASL_EXEC(basl_table_append_int(table, 0, size));
+
+ return (0);
+}
+
int
basl_table_create(struct basl_table **const table, struct vmctx *ctx,
const uint8_t *const name, const uint32_t alignment,
@@ -376,6 +508,7 @@
STAILQ_INIT(&new_table->checksums);
STAILQ_INIT(&new_table->lengths);
+ STAILQ_INIT(&new_table->pointers);
STAILQ_INSERT_TAIL(&basl_tables, new_table, chain);

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 16, 5:18 PM (21 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14661948
Default Alt Text
D36991.diff (5 KB)

Event Timeline