From nobody Tue Nov 29 13:58:04 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NM3nm6Kb8z4htxt; Tue, 29 Nov 2022 13:58:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NM3nm5cZlz4Cnv; Tue, 29 Nov 2022 13:58:04 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1669730284; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=0EJ6LFTTOiLwjbknxaiqy6y+evHt5JTNeHi5dWLxGsM=; b=E5uhtod+DNQLDm/6EMPydWxb7OSI1RG1thYAON6Lf6N0bTQrtQEOqhc39cWorvHrBIUJlx pmwvmpWT/tlBfyYDQgmaDl8k7erVQ96/6tWY3qtYVsR97jlyfvYw/PbvLwboMKA7dKpe1G y55GligjDWMOh/Zca8B3FE7aFO2gMOLgLML672bELG7IoNcHIKq9I+P0AkxTPK4BFooL+F aXPVOqtsY6f8oVC2RUgNtnL3k4CRG4felPxI7JDaJf4JPzeq+WOAFLBc4Ir4hKgDRDVadL 36k3HKdQ+riNj8Y3FR9LUMhDWwJI9BEio/QOejVXRJkHUeuo95gPwvd/EYAK8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1669730284; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=0EJ6LFTTOiLwjbknxaiqy6y+evHt5JTNeHi5dWLxGsM=; b=rohMAbhB6Noq2e3ph26cFQv9ATfh2SO8U7yqXWNSmblWnpRPXUqQyAms3ma4jtsmCtTC66 tpHNari0YkNaUw10Dlc1lpdcm72ervA0XkWd6puZQ/0sF69eiea2FkQPIU81u3QZEUQfxX iGQR506FL4hk2Jdkos2Mfe5VQsbW0PGzNQV2UIgWMLkswsYPj5+Gi+vgFSZZl61be6OUgA xm5ubRn6DtIcytHgwkLV5gSC8fk2TXUicsAqIMmapPXfcMJikOBwfOsJPj3/mEb+5EHHlQ Ag2XH4xRK6e0wG9Zo8XacQvddjJZOHi968870vIYnD7b5UCzXag9PPL/1K31WA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1669730284; a=rsa-sha256; cv=none; b=a65aYwW4iaaGBNl2Dr15L/3fuV3DOAN4lDwcHaG46KCW6JI+kvDPygkFnThrN/6tywlWcZ MSXEYtXO9a3Azw2VNZXWgSpWlD5QSEKPs/Lw8XoKtJr5QYe4f2Jgwsb1IxolPKhKRZX9t7 vnkdzGIRx6sw1IQ/KnzCQ8qfZjSMAK6VY825gtzWgpVAblpCJJDx0qQXKP29JwgSZMjbfh dV10L+OVHBFH36JKr3mAURLeHtN9GsH8tI87iG2tgC4Jt4cZgWyaMfw7en1gIbDD77txrI VsoZSMoDD7yOklTnLj84yotRxKXXdRW3zZmbRUICC702HtRX4JT9rp/KLYzHxg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NM3nm4V2vzKSs; Tue, 29 Nov 2022 13:58:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2ATDw4iB029504; Tue, 29 Nov 2022 13:58:04 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2ATDw41h029503; Tue, 29 Nov 2022 13:58:04 GMT (envelope-from git) Date: Tue, 29 Nov 2022 13:58:04 GMT Message-Id: <202211291358.2ATDw41h029503@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: =?utf-8?Q?Corvin=20K=C3=B6hne?= Subject: git: 30ab6a9ee05d - stable/13 - bhyve: add basl support for checksums List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: corvink X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 30ab6a9ee05d1c3a06df3c2449fe5c320e8dcdbd Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by corvink: URL: https://cgit.FreeBSD.org/src/commit/?id=30ab6a9ee05d1c3a06df3c2449fe5c320e8dcdbd commit 30ab6a9ee05d1c3a06df3c2449fe5c320e8dcdbd Author: Corvin Köhne AuthorDate: 2022-04-06 09:10:39 +0000 Commit: Corvin Köhne CommitDate: 2022-11-29 13:53:52 +0000 bhyve: add basl support for checksums The qemu ACPI table loader patches the ACPI tables. After patching them, checksums aren't correct any more. It has to calculate a new checksum for the ACPI table. For that reason, basl has to keep track of checksums and has to cause the qemu loader to create new checksums for the tables. The qemu ACPI table loader isn't supported yet. However, the address of all tables is unknown as long as bhyve hasn't finished ACPI table creation. So, the checksum of tables which include pointer to other tables are unknown too. This requires tracking of checksums too. Reviewed by: jhb Approved by: manu (mentor) MFC after: 2 weeks Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D36990 (cherry picked from commit 29578470314c09d4ae3163f151da7d4684fb1428) --- usr.sbin/bhyve/basl.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ usr.sbin/bhyve/basl.h | 4 ++ 2 files changed, 116 insertions(+) diff --git a/usr.sbin/bhyve/basl.c b/usr.sbin/bhyve/basl.c index b03c936bd517..77f26a930b94 100644 --- a/usr.sbin/bhyve/basl.c +++ b/usr.sbin/bhyve/basl.c @@ -21,6 +21,13 @@ #include "basl.h" +struct basl_table_checksum { + STAILQ_ENTRY(basl_table_checksum) chain; + uint32_t off; + uint32_t start; + uint32_t len; +}; + struct basl_table_length { STAILQ_ENTRY(basl_table_length) chain; uint32_t off; @@ -35,6 +42,8 @@ struct basl_table { uint32_t len; uint32_t off; uint32_t alignment; + STAILQ_HEAD(basl_table_checksum_list, + basl_table_checksum) checksums; STAILQ_HEAD(basl_table_length_list, basl_table_length) lengths; }; static STAILQ_HEAD(basl_table_list, basl_table) basl_tables = STAILQ_HEAD_INITIALIZER( @@ -109,6 +118,64 @@ basl_finish_install_guest_tables(struct basl_table *const table) return (0); } +static int +basl_finish_patch_checksums(struct basl_table *const table) +{ + struct basl_table_checksum *checksum; + + STAILQ_FOREACH(checksum, &table->checksums, chain) { + uint8_t *gva, *checksum_gva; + uint64_t gpa; + uint32_t len; + uint8_t sum; + + len = checksum->len; + if (len == BASL_TABLE_CHECKSUM_LEN_FULL_TABLE) { + len = table->len; + } + + assert(checksum->off < table->len); + assert(checksum->start < table->len); + assert(checksum->start + len <= table->len); + + /* + * 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 + checksum->start; + if ((gpa < BHYVE_ACPI_BASE) || + (gpa < BHYVE_ACPI_BASE + table->off)) { + warnx("%s: invalid gpa (off 0x%8x start 0x%8x)", + __func__, table->off, checksum->start); + return (EFAULT); + } + + gva = vm_map_gpa(table->ctx, gpa, len); + if (gva == NULL) { + warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]", + __func__, gpa, gpa + len); + return (ENOMEM); + } + + checksum_gva = gva + checksum->off; + if (checksum_gva < gva) { + warnx("%s: invalid checksum offset 0x%8x", __func__, + checksum->off); + return (EFAULT); + } + + sum = 0; + for (uint32_t i = 0; i < len; ++i) { + sum += *(gva + i); + } + *checksum_gva = -sum; + } + + return (0); +} + static int basl_finish_set_length(struct basl_table *const table) { @@ -135,10 +202,21 @@ basl_finish(void) return (EINVAL); } + /* + * We have to install all tables before we can patch them. Therefore, + * use two loops. The first one installs all tables and the second one + * patches them. + */ STAILQ_FOREACH(table, &basl_tables, chain) { BASL_EXEC(basl_finish_set_length(table)); BASL_EXEC(basl_finish_install_guest_tables(table)); } + STAILQ_FOREACH(table, &basl_tables, chain) { + /* + * Calculate the checksum as last step! + */ + BASL_EXEC(basl_finish_patch_checksums(table)); + } return (0); } @@ -149,6 +227,27 @@ basl_init(void) return (0); } +static int +basl_table_add_checksum(struct basl_table *const table, const uint32_t off, + const uint32_t start, const uint32_t len) +{ + struct basl_table_checksum *checksum; + + checksum = calloc(1, sizeof(struct basl_table_checksum)); + if (checksum == NULL) { + warnx("%s: failed to allocate checksum", __func__); + return (ENOMEM); + } + + checksum->off = off; + checksum->start = start; + checksum->len = len; + + STAILQ_INSERT_TAIL(&table->checksums, checksum, chain); + + return (0); +} + static int basl_table_add_length(struct basl_table *const table, const uint32_t off, const uint8_t size) @@ -200,6 +299,18 @@ basl_table_append_bytes(struct basl_table *const table, const void *const bytes, return (0); } +int +basl_table_append_checksum(struct basl_table *const table, const uint32_t start, + const uint32_t len) +{ + assert(table != NULL); + + BASL_EXEC(basl_table_add_checksum(table, table->len, start, len)); + BASL_EXEC(basl_table_append_int(table, 0, 1)); + + return (0); +} + int basl_table_append_gas(struct basl_table *const table, const uint8_t space_id, const uint8_t bit_width, const uint8_t bit_offset, @@ -263,6 +374,7 @@ basl_table_create(struct basl_table **const table, struct vmctx *ctx, new_table->alignment = alignment; new_table->off = off; + STAILQ_INIT(&new_table->checksums); STAILQ_INIT(&new_table->lengths); STAILQ_INSERT_TAIL(&basl_tables, new_table, chain); diff --git a/usr.sbin/bhyve/basl.h b/usr.sbin/bhyve/basl.h index 95c5fd916761..b478780cb74d 100644 --- a/usr.sbin/bhyve/basl.h +++ b/usr.sbin/bhyve/basl.h @@ -20,6 +20,8 @@ #define BASL_TABLE_ALIGNMENT 0x10 #define BASL_TABLE_ALIGNMENT_FACS 0x40 +#define BASL_TABLE_CHECKSUM_LEN_FULL_TABLE (-1) + #define BASL_EXEC(x) \ do { \ const int error = (x); \ @@ -39,6 +41,8 @@ int basl_finish(void); int basl_init(void); int basl_table_append_bytes(struct basl_table *table, const void *bytes, uint32_t len); +int basl_table_append_checksum(struct basl_table *table, uint32_t start, + uint32_t len); int basl_table_append_gas(struct basl_table *table, uint8_t space_id, uint8_t bit_width, uint8_t bit_offset, uint8_t access_width, uint64_t address);