Cihula, Joseph
2009-Jan-20 05:49 UTC
[Xen-devel] [PATCH] txt: 3/6 - use TXT''s DMA-protected DMAR table to setup VT-d
The VT-d DMAR ACPI tables may not be DMA protected by tboot. However, SINIT saves a copy of them in the SinitMleData struct in the TXT heap (which is DMA protected). So we should read the DMAR table from that copy if launched by tboot. Signed-off-by: Joseph Cihula <joseph.cihula@intel.com> diff -r bde0fd053306 -r a851239c01cb xen/arch/x86/tboot.c --- a/xen/arch/x86/tboot.c Fri Jan 16 13:34:36 2009 -0800 +++ b/xen/arch/x86/tboot.c Fri Jan 16 13:43:15 2009 -0800 @@ -20,6 +20,9 @@ uint64_t txt_protmem_range_ends[TXT_PROT uint64_t txt_protmem_range_ends[TXT_PROTMEM_RANGE_MAX]; static const uuid_t tboot_shared_uuid = TBOOT_SHARED_UUID; + +/* used by tboot_probe() and tboot_parse_dmar_table() */ +static uint64_t txt_heap_base, txt_heap_size; void __init tboot_probe(void) { @@ -68,6 +71,7 @@ void __init tboot_probe(void) size = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_HEAP_SIZE); txt_protmem_range_starts[0] = base; txt_protmem_range_ends[0] = base + size - 1; + txt_heap_base = base; txt_heap_size = size; /* SINIT */ base = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_BASE); @@ -142,6 +146,56 @@ int tboot_in_range(paddr_t start, paddr_ return start < end; } +int __init tboot_parse_dmar_table(acpi_table_handler dmar_handler) +{ + uint32_t map_base, map_size; + unsigned long map_vaddr; + void *heap_ptr; + struct acpi_table_header *dmar_table; + int rc; + + if ( !tboot_in_measured_env() ) + return acpi_table_parse(ACPI_SIG_DMAR, dmar_handler); + + /* ACPI tables may not be DMA protected by tboot, so use DMAR copy */ + /* SINIT saved in SinitMleData in TXT heap (which is DMA protected) */ + + /* map TXT heap into Xen addr space */ + map_base = PFN_DOWN(txt_heap_base); + map_size = PFN_UP(txt_heap_size); + map_vaddr = (unsigned long)__va(map_base << PAGE_SHIFT); + if ( map_pages_to_xen(map_vaddr, map_base, map_size, __PAGE_HYPERVISOR) ) + return 1; + + /* walk heap to SinitMleData */ + heap_ptr = __va(txt_heap_base); + /* skip BiosData */ + heap_ptr += *(uint64_t *)heap_ptr; + /* skip OsMleData */ + heap_ptr += *(uint64_t *)heap_ptr; + /* skip OsSinitData */ + heap_ptr += *(uint64_t *)heap_ptr; + /* now points to SinitMleDataSize; set to SinitMleData */ + heap_ptr += sizeof(uint64_t); + /* get addr of DMAR table */ + dmar_table = (struct acpi_table_header *)(heap_ptr + + ((sinit_mle_data_t *)heap_ptr)->vtd_dmars_off - sizeof(uint64_t)); + + rc = dmar_handler(dmar_table); + + /* acpi_parse_dmar() zaps APCI DMAR signature in TXT heap table */ + /* but dom0 will read real table, so must zap it there too */ + dmar_table = NULL; + acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_table); + if ( dmar_table != NULL ) + ((struct acpi_table_dmar *)dmar_table)->header.signature[0] = ''\0''; + + destroy_xen_mappings((unsigned long)__va(map_base << PAGE_SHIFT), + (unsigned long)__va((map_base + map_size) << PAGE_SHIFT)); + + return rc; +} + /* * Local variables: * mode: C diff -r bde0fd053306 -r a851239c01cb xen/drivers/passthrough/vtd/dmar.c --- a/xen/drivers/passthrough/vtd/dmar.c Fri Jan 16 13:34:36 2009 -0800 +++ b/xen/drivers/passthrough/vtd/dmar.c Fri Jan 16 13:43:15 2009 -0800 @@ -28,6 +28,7 @@ #include <xen/pci.h> #include <xen/pci_regs.h> #include <asm/string.h> +#include <asm/tboot.h> #include "dmar.h" int vtd_enabled = 1; @@ -516,7 +517,9 @@ int acpi_dmar_init(void) if ( !iommu_enabled ) goto fail; - rc = acpi_table_parse(ACPI_SIG_DMAR, acpi_parse_dmar); + /* ACPI tables may not be DMA protected by tboot, so use DMAR copy */ + /* SINIT saved in SinitMleData in TXT heap (which is DMA protected) */ + rc = tboot_parse_dmar_table(acpi_parse_dmar); if ( rc ) goto fail; diff -r bde0fd053306 -r a851239c01cb xen/include/asm-x86/tboot.h --- a/xen/include/asm-x86/tboot.h Fri Jan 16 13:34:36 2009 -0800 +++ b/xen/include/asm-x86/tboot.h Fri Jan 16 13:43:15 2009 -0800 @@ -37,7 +37,13 @@ #ifndef __TBOOT_H__ #define __TBOOT_H__ -typedef struct __attribute__ ((__packed__)) { +#include <xen/acpi.h> + +#ifndef __packed +#define __packed __attribute__ ((packed)) +#endif + +typedef struct __packed { uint32_t data1; uint16_t data2; uint16_t data3; @@ -47,7 +53,7 @@ typedef struct __attribute__ ((__packed_ /* used to communicate between tboot and the launched kernel (i.e. Xen) */ -typedef struct __attribute__ ((__packed__)) { +typedef struct __packed { uint16_t pm1a_cnt; uint16_t pm1b_cnt; uint16_t pm1a_evt; @@ -56,7 +62,7 @@ typedef struct __attribute__ ((__packed_ uint16_t pm1b_cnt_val; } tboot_acpi_sleep_info; -typedef struct __attribute__ ((__packed__)) { +typedef struct __packed { /* version 0x01+ fields: */ uuid_t uuid; /* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */ uint32_t version; /* Version number: 0x01, 0x02, ... */ @@ -89,6 +95,7 @@ void tboot_probe(void); void tboot_probe(void); void tboot_shutdown(uint32_t shutdown_type); int tboot_in_measured_env(void); +int tboot_parse_dmar_table(acpi_table_handler dmar_handler); /* * TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_BASE) @@ -106,6 +113,27 @@ int tboot_in_measured_env(void); #define TXTCR_HEAP_BASE 0x0300 #define TXTCR_HEAP_SIZE 0x0308 +#define SHA1_SIZE 20 +typedef uint8_t sha1_hash_t[SHA1_SIZE]; + +typedef struct __packed { + uint32_t version; /* currently 6 */ + sha1_hash_t bios_acm_id; + uint32_t edx_senter_flags; + uint64_t mseg_valid; + sha1_hash_t sinit_hash; + sha1_hash_t mle_hash; + sha1_hash_t stm_hash; + sha1_hash_t lcp_policy_hash; + uint32_t lcp_policy_control; + uint32_t rlp_wakeup_addr; + uint32_t reserved; + uint32_t num_mdrs; + uint32_t mdrs_off; + uint32_t num_vtd_dmars; + uint32_t vtd_dmars_off; +} sinit_mle_data_t; + #define TXT_PROTMEM_RANGE_MAX 3 extern uint64_t txt_protmem_range_starts[TXT_PROTMEM_RANGE_MAX]; extern uint64_t txt_protmem_range_ends[TXT_PROTMEM_RANGE_MAX]; _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel