[PATCH] txt: 3/6 - use TXT's DMA-protected DMAR table to setup VT-d

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] txt: 3/6 - use TXT's DMA-protected DMAR table to setup VT-d

Cihula, Joseph
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 <[hidden email]>

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];

_______________________________________________
Xense-devel mailing list
[hidden email]
http://lists.xensource.com/xense-devel

xen-txt-03-use_protected_dmar.patch (8K) Download Attachment