Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP2:Update
tboot.18210
tboot-Configure-IOMMU-before-executing-GETSEC-S...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File tboot-Configure-IOMMU-before-executing-GETSEC-SENTER.patch of Package tboot.18210
From 4ab3384cd765def9a4ca00791341d47c35b8912a Mon Sep 17 00:00:00 2001 From: Lukasz Hawrylko <lukasz.hawrylko@intel.com> Date: Mon, 21 Oct 2019 12:09:04 +0200 Subject: [PATCH] Configure IOMMU before executing GETSEC[SENTER] SINIT required that following IOMMU features are disabled: - DMA remapping (done in TBOOT) - Queued Invalidation (done in SINIT) - Interrupt Remapping (done in SINIT) Signed-off-by: Lukasz Hawrylko <lukasz.hawrylko@intel.com> --- tboot/Makefile | 2 +- tboot/common/acpi.c | 77 +---------- tboot/common/tboot.c | 7 +- tboot/common/vtd.c | 220 ++++++++++++++++++++++++++++++++ tboot/include/acpi.h | 3 +- tboot/include/txt/config_regs.h | 27 ++-- tboot/include/vtd.h | 64 ++++++++++ tboot/txt/txt.c | 41 +++++- tboot/txt/verify.c | 1 + 9 files changed, 355 insertions(+), 87 deletions(-) create mode 100644 tboot/common/vtd.c create mode 100644 tboot/include/vtd.h Index: tboot-1.9.8/tboot/Makefile =================================================================== --- tboot-1.9.8.orig/tboot/Makefile +++ tboot-1.9.8/tboot/Makefile @@ -13,7 +13,7 @@ TARGET := $(CURDIR)/tboot # boot.o must be first obj-y := common/boot.o -obj-y += common/acpi.o common/cmdline.o common/com.o common/e820.o +obj-y += common/acpi.o common/cmdline.o common/com.o common/e820.o common/vtd.o obj-y += common/elf.o common/hash.o common/index.o common/integrity.o obj-y += common/linux.o common/loader.o common/memcmp.o common/memcpy.o obj-y += common/misc.o common/mutex.o common/paging.o common/pci_cfgreg.o Index: tboot-1.9.8/tboot/common/acpi.c =================================================================== --- tboot-1.9.8.orig/tboot/common/acpi.c +++ tboot-1.9.8/tboot/common/acpi.c @@ -53,8 +53,6 @@ #endif static struct acpi_rsdp *rsdp; -static struct acpi_table_header *g_dmar_table; -static __data bool g_hide_dmar; static void dump_gas(const char *reg_name, const tboot_acpi_generic_address_t *reg) @@ -216,76 +214,6 @@ static struct acpi_table_header *find_ta return NULL; } -static struct acpi_dmar *get_vtd_dmar_table(void) -{ - return (struct acpi_dmar *)find_table(DMAR_SIG); -} - -bool vtd_bios_enabled(void) -{ - return find_table(DMAR_SIG) != NULL; -} - -bool save_vtd_dmar_table(void) -{ - /* find DMAR table and save it */ - g_dmar_table = (struct acpi_table_header *)get_vtd_dmar_table(); - - printk(TBOOT_DETA"DMAR table @ %p saved.\n", g_dmar_table); - return true; -} - -bool restore_vtd_dmar_table(void) -{ - struct acpi_table_header *hdr; - - g_hide_dmar = false; - - /* find DMAR table first */ - hdr = (struct acpi_table_header *)get_vtd_dmar_table(); - if ( hdr != NULL ) { - printk(TBOOT_DETA"DMAR table @ %p is still there, skip restore step.\n", hdr); - return true; - } - - /* check saved DMAR table */ - if ( g_dmar_table == NULL ) { - printk(TBOOT_ERR"No DMAR table saved, abort restore step.\n"); - return false; - } - - /* restore DMAR if needed */ - memcpy(g_dmar_table->signature, DMAR_SIG, sizeof(g_dmar_table->signature)); - - /* need to hide DMAR table while resume from S3 */ - g_hide_dmar = true; - printk(TBOOT_DETA"DMAR table @ %p restored.\n", hdr); - return true; -} - -bool remove_vtd_dmar_table(void) -{ - struct acpi_table_header *hdr; - - /* check whether it is needed */ - if ( !g_hide_dmar ) { - printk(TBOOT_DETA"No need to hide DMAR table.\n"); - return true; - } - - /* find DMAR table */ - hdr = (struct acpi_table_header *)get_vtd_dmar_table(); - if ( hdr == NULL ) { - printk(TBOOT_DETA"No DMAR table, skip remove step.\n"); - return true; - } - - /* remove DMAR table */ - hdr->signature[0] = '\0'; - printk(TBOOT_DETA"DMAR table @ %p removed.\n", hdr); - return true; -} - static struct acpi_madt *get_apic_table(void) { return (struct acpi_madt *)find_table(MADT_SIG); @@ -333,6 +261,11 @@ struct acpi_mcfg *get_acpi_mcfg_table(vo return (struct acpi_mcfg *)find_table(MCFG_SIG); } +struct acpi_dmar *get_vtd_dmar_table(void) +{ + return (struct acpi_dmar *)find_table(DMAR_SIG); +} + static bool write_to_reg(const tboot_acpi_generic_address_t *reg, uint32_t val) { Index: tboot-1.9.8/tboot/common/tboot.c =================================================================== --- tboot-1.9.8.orig/tboot/common/tboot.c +++ tboot-1.9.8/tboot/common/tboot.c @@ -70,6 +70,7 @@ #include <integrity.h> #include <cmdline.h> #include <tpm_20.h> +#include <vtd.h> extern void _prot_to_real(uint32_t dist_addr); extern bool set_policy(void); @@ -170,7 +171,7 @@ static void post_launch(void) /* backup DMAR table */ if ( get_tboot_save_vtd() ) - save_vtd_dmar_table(); + vtd_save_dmar_table(); if ( s3_flag ) s3_launch(); @@ -475,7 +476,7 @@ void s3_launch(void) /* remove DMAR table if necessary */ if ( get_tboot_save_vtd() ) - remove_vtd_dmar_table(); + vtd_remove_dmar_table(); if ( !is_launched() ) apply_policy(TB_ERR_S3_INTEGRITY); @@ -594,7 +595,7 @@ void shutdown(void) if ( _tboot_shared.shutdown_type == TB_SHUTDOWN_S3 ) { /* restore DMAR table if needed */ if ( get_tboot_save_vtd() ) - restore_vtd_dmar_table(); + vtd_restore_dmar_table(); if ( tpm->major == TPM20_VER_MAJOR ) { tpm_fp->context_flush(tpm, tpm->cur_loc, handle2048); tpm_fp->context_load(tpm, tpm->cur_loc, &tpm2_context_saved, &handle2048); Index: tboot-1.9.8/tboot/common/vtd.c =================================================================== --- /dev/null +++ tboot-1.9.8/tboot/common/vtd.c @@ -0,0 +1,220 @@ +/* + * vtd.c: VT-d support functions + * + * Copyright (c) 2019, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <types.h> +#include <stdbool.h> +#include <compiler.h> +#include <processor.h> +#include <printk.h> +#include <tboot.h> +#include <loader.h> +#include <string.h> +#include <acpi.h> +#include <txt/config_regs.h> + +#include <vtd.h> + +static struct acpi_table_header *g_dmar_table; +static __data bool g_hide_dmar; + +bool vtd_bios_enabled(void) +{ + return get_vtd_dmar_table() != NULL; +} + +bool vtd_save_dmar_table(void) +{ + /* find DMAR table and save it */ + g_dmar_table = (struct acpi_table_header *)get_vtd_dmar_table(); + + printk(TBOOT_DETA"DMAR table @ %p saved.\n", g_dmar_table); + return true; +} + +bool vtd_restore_dmar_table(void) +{ + struct acpi_table_header *hdr; + + g_hide_dmar = false; + + /* find DMAR table first */ + hdr = (struct acpi_table_header *)get_vtd_dmar_table(); + if ( hdr != NULL ) { + printk(TBOOT_DETA"DMAR table @ %p is still there, skip restore step.\n", hdr); + return true; + } + + /* check saved DMAR table */ + if ( g_dmar_table == NULL ) { + printk(TBOOT_ERR"No DMAR table saved, abort restore step.\n"); + return false; + } + + /* restore DMAR if needed */ + memcpy(g_dmar_table->signature, DMAR_SIG, sizeof(g_dmar_table->signature)); + + /* need to hide DMAR table while resume from S3 */ + g_hide_dmar = true; + printk(TBOOT_DETA"DMAR table @ %p restored.\n", hdr); + return true; +} + +bool vtd_remove_dmar_table(void) +{ + struct acpi_table_header *hdr; + + /* check whether it is needed */ + if ( !g_hide_dmar ) { + printk(TBOOT_DETA"No need to hide DMAR table.\n"); + return true; + } + + /* find DMAR table */ + hdr = (struct acpi_table_header *)get_vtd_dmar_table(); + if ( hdr == NULL ) { + printk(TBOOT_DETA"No DMAR table, skip remove step.\n"); + return true; + } + + /* remove DMAR table */ + hdr->signature[0] = '\0'; + printk(TBOOT_DETA"DMAR table @ %p removed.\n", hdr); + return true; +} + +struct dmar_remapping *vtd_get_dmar_remap(uint32_t *remap_length) +{ + struct acpi_dmar *dmar = get_vtd_dmar_table(); + + if (dmar == NULL || remap_length == NULL) { + return NULL; + } + + *remap_length = dmar->hdr.length - sizeof(*dmar); + return (struct dmar_remapping*)(dmar->table_offsets); +} + +bool vtd_disable_dma_remap(struct dmar_remapping *rs) +{ + if (rs->type != DMAR_REMAPPING_DRHD) { + return false; + } + + uint32_t timeout; + uint32_t gsts = read_reg32(rs->register_base_address, VTD_GSTS_OFFSET) & 0x96FFFFFF; + + if (gsts & TE_STAT) { + /* Clear TE_STAT bit and write back to GCMD */ + gsts &= ~TE_STAT; + write_reg32(rs->register_base_address, VTD_GCMD_OFFSET, gsts); + + /* Wait until GSTS indicates that operation is completed */ + timeout = VTD_OPERATION_TIMEOUT; + while (read_reg32(rs->register_base_address, VTD_GSTS_OFFSET) & TE_STAT) { + cpu_relax(); + if (--timeout == 0) { + return false; + } + } + } + + return true; +} + +bool vtd_disable_qie(struct dmar_remapping *rs) +{ + if (rs->type != DMAR_REMAPPING_DRHD) { + return false; + } + + uint32_t timeout; + uint32_t gsts = read_reg32(rs->register_base_address, VTD_GSTS_OFFSET) & 0x96FFFFFF; + + if (gsts & QIE_STAT) { + /* Wait for HW to complete pending invalidation requests */ + timeout = VTD_OPERATION_TIMEOUT; + while (read_reg64(rs->register_base_address, VTD_IQT_OFFSET) != + read_reg64(rs->register_base_address, VTD_IQH_OFFSET)) { + cpu_relax(); + if (--timeout == 0) { + return false; + } + } + + /* Clear QIE_STAT bit and write back to GCMD */ + gsts &= ~QIE_STAT; + write_reg32(rs->register_base_address, VTD_GCMD_OFFSET, gsts); + + /* Wait until GSTS indicates that operation is completed */ + timeout = VTD_OPERATION_TIMEOUT; + while (read_reg32(rs->register_base_address, VTD_GSTS_OFFSET) & QIE_STAT) { + cpu_relax(); + if (--timeout == 0) { + return false; + } + } + + /* Set IQT to 0 (IQH was set by HW) */ + write_reg64(rs->register_base_address, VTD_IQT_OFFSET, 0); + } + + return true; +} + +bool vtd_disable_ire(struct dmar_remapping *rs) +{ + if (rs->type != DMAR_REMAPPING_DRHD) { + return false; + } + + uint32_t timeout; + uint32_t gsts = read_reg32(rs->register_base_address, VTD_GSTS_OFFSET) & 0x96FFFFFF; + + if (gsts & IRE_STAT) { + /* Clear IRE_STAT bit and write back to GCMD */ + gsts &= ~IRE_STAT; + write_reg32(rs->register_base_address, VTD_GCMD_OFFSET, gsts); + + /* Wait until GSTS indicates that operation is completed */ + timeout = VTD_OPERATION_TIMEOUT; + while (read_reg32(rs->register_base_address, VTD_GSTS_OFFSET) & IRE_STAT) { + cpu_relax(); + if (--timeout == 0) { + return false; + } + } + } + + return true; +} \ No newline at end of file Index: tboot-1.9.8/tboot/include/acpi.h =================================================================== --- tboot-1.9.8.orig/tboot/include/acpi.h +++ tboot-1.9.8/tboot/include/acpi.h @@ -356,7 +356,7 @@ struct dmar_remapping { u_int8_t reserved; u_int16_t segment_number; - u_int8_t register_base_address[8]; + u_int64_t register_base_address; struct device_scope device_scope_entry[1]; /* Device Scope starts here */ } __packed; @@ -498,6 +498,7 @@ extern bool remove_vtd_dmar_table(void); extern struct acpi_table_ioapic *get_acpi_ioapic_table(void); extern struct acpi_mcfg *get_acpi_mcfg_table(void); +extern struct acpi_dmar *get_vtd_dmar_table(void); extern void disable_smis(void); extern bool machine_sleep(const tboot_acpi_sleep_info_t *); Index: tboot-1.9.8/tboot/include/txt/config_regs.h =================================================================== --- tboot-1.9.8.orig/tboot/include/txt/config_regs.h +++ tboot-1.9.8/tboot/include/txt/config_regs.h @@ -190,39 +190,48 @@ typedef struct { * fns to read/write TXT config regs */ -#ifndef IS_INCLUDED -static inline uint64_t read_config_reg(uint32_t config_regs_base, uint32_t reg) +static inline uint64_t read_reg64(uint32_t config_regs_base, uint32_t reg) { /* these are MMIO so make sure compiler doesn't optimize */ return *(volatile uint64_t *)(unsigned long)(config_regs_base + reg); } -#endif -static inline void write_config_reg(uint32_t config_regs_base, uint32_t reg, - uint64_t val) +static inline uint32_t read_reg32(uint32_t config_regs_base, uint32_t reg) +{ + /* these are MMIO so make sure compiler doesn't optimize */ + return *(volatile uint32_t *)(unsigned long)(config_regs_base + reg); +} + +static inline void write_reg64(uint32_t config_regs_base, uint32_t reg, uint64_t val) { /* these are MMIO so make sure compiler doesn't optimize */ *(volatile uint64_t *)(unsigned long)(config_regs_base + reg) = val; } +static inline void write_reg32(uint32_t config_regs_base, uint32_t reg, uint32_t val) +{ + /* these are MMIO so make sure compiler doesn't optimize */ + *(volatile uint32_t *)(unsigned long)(config_regs_base + reg) = val; +} + static inline uint64_t read_pub_config_reg(uint32_t reg) { - return read_config_reg(TXT_PUB_CONFIG_REGS_BASE, reg); + return read_reg64(TXT_PUB_CONFIG_REGS_BASE, reg); } static inline void write_pub_config_reg(uint32_t reg, uint64_t val) { - write_config_reg(TXT_PUB_CONFIG_REGS_BASE, reg, val); + write_reg64(TXT_PUB_CONFIG_REGS_BASE, reg, val); } static inline uint64_t read_priv_config_reg(uint32_t reg) { - return read_config_reg(TXT_PRIV_CONFIG_REGS_BASE, reg); + return read_reg64(TXT_PRIV_CONFIG_REGS_BASE, reg); } static inline void write_priv_config_reg(uint32_t reg, uint64_t val) { - write_config_reg(TXT_PRIV_CONFIG_REGS_BASE, reg, val); + write_reg64(TXT_PRIV_CONFIG_REGS_BASE, reg, val); } #endif /* __TXT_CONFIG_REGS_H__ */ Index: tboot-1.9.8/tboot/include/vtd.h =================================================================== --- /dev/null +++ tboot-1.9.8/tboot/include/vtd.h @@ -0,0 +1,64 @@ +/* + * vtd.c: VT-d support functions + * + * Copyright (c) 2019, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __VTD_H__ +#define __VTD_H__ + +#define VTD_OPERATION_TIMEOUT 0x10000000 + +#define VTD_GCMD_OFFSET 0x18 + #define TE_EN (1 << 31) + #define QIE_EN (1 << 26) + #define IRE_EN (1 << 25) + +#define VTD_GSTS_OFFSET 0x1C + #define TE_STAT (1 << 31) + #define QIE_STAT (1 << 26) + #define IRE_STAT (1 << 25) + +#define VTD_IQH_OFFSET 0x80 +#define VTD_IQT_OFFSET 0x88 + +bool vtd_bios_enabled(void); +bool vtd_save_dmar_table(void); +bool vtd_restore_dmar_table(void); +bool vtd_remove_dmar_table(void); + +struct dmar_remapping *vtd_get_dmar_remap(uint32_t *remap_length); +bool vtd_disable_dma_remap(struct dmar_remapping *rs); +bool vtd_disable_qie(struct dmar_remapping *rs); +bool vtd_disable_ire(struct dmar_remapping *rs); + +#endif \ No newline at end of file Index: tboot-1.9.8/tboot/txt/txt.c =================================================================== --- tboot-1.9.8.orig/tboot/txt/txt.c +++ tboot-1.9.8/tboot/txt/txt.c @@ -56,6 +56,7 @@ #include <hash.h> #include <cmdline.h> #include <acpi.h> +#include <vtd.h> #include <txt/txt.h> #include <txt/config_regs.h> #include <txt/mtrrs.h> @@ -527,6 +528,42 @@ bool evtlog_append(uint8_t pcr, hash_lis __data uint32_t g_using_da = 0; __data acm_hdr_t *g_sinit = 0; +static void configure_vtd(void) +{ + uint32_t remap_length; + struct dmar_remapping *dmar_remap = vtd_get_dmar_remap(&remap_length); + + if (dmar_remap == NULL) { + printk("cannot get DMAR remapping strucutues, skiping configuration\n"); + return; + } else { + printk("configuring DMAR remapping\n"); + } + + struct dmar_remapping *iter, *next; + struct dmar_remapping *end = ((void *)dmar_remap) + remap_length; + + for (iter = dmar_remap; iter < end; iter = next) { + next = (void *)iter + iter->length; + if (iter->length == 0) { + /* Avoid looping forever on bad ACPI tables */ + printk(" invalid 0-length structure\n"); + break; + } else if (next > end) { + /* Avoid passing table end */ + printk(" record passes table end\n"); + break; + } + + if (iter->type == DMAR_REMAPPING_DRHD) { + if (!vtd_disable_dma_remap(iter)) { + printk(" vtd_disable_dma_remap failed!\n"); + } + } + } + +} + /* * sets up TXT heap */ @@ -811,6 +848,8 @@ tb_error_t txt_launch_environment(loader if ( mle_ptab_base == NULL ) return TB_ERR_FATAL; + configure_vtd(); + /* initialize TXT heap */ txt_heap = init_txt_heap(mle_ptab_base, g_sinit, lctx); if ( txt_heap == NULL ) @@ -867,7 +906,7 @@ bool txt_s3_launch_environment(void) return false; } /* initialize event log in os_sinit_data, so that events will not */ - /* repeat when s3 */ + /* repeat when s3 */ if ( log_type == EVTLOG_TPM12 && g_elog ) { g_elog = (event_log_container_t *)init_event_log(); } else if ( log_type == EVTLOG_TPM2_TCG && g_elog_2_1) { Index: tboot-1.9.8/tboot/txt/verify.c =================================================================== --- tboot-1.9.8.orig/tboot/txt/verify.c +++ tboot-1.9.8/tboot/txt/verify.c @@ -53,6 +53,7 @@ #include <hash.h> #include <integrity.h> #include <cmdline.h> +#include <vtd.h> #include <txt/txt.h> #include <txt/smx.h> #include <txt/mtrrs.h>
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor