ia64/xen-unstable

changeset 19117:31798b19f25c

tboot: use TXT's DMA-protected DMAR table to setup VT-d

Signed-off-by: Joseph Cihula <joseph.cihula@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jan 29 12:44:31 2009 +0000 (2009-01-29)
parents 202afa5384c4
children 259d6ac13704
files xen/arch/x86/tboot.c xen/drivers/passthrough/vtd/dmar.c xen/include/asm-x86/tboot.h
line diff
     1.1 --- a/xen/arch/x86/tboot.c	Thu Jan 29 12:10:39 2009 +0000
     1.2 +++ b/xen/arch/x86/tboot.c	Thu Jan 29 12:44:31 2009 +0000
     1.3 @@ -18,6 +18,10 @@ tboot_shared_t *g_tboot_shared;
     1.4  
     1.5  static const uuid_t tboot_shared_uuid = TBOOT_SHARED_UUID;
     1.6  
     1.7 +/* used by tboot_protect_mem_regions() and/or tboot_parse_dmar_table() */
     1.8 +static uint64_t txt_heap_base, txt_heap_size;
     1.9 +static uint64_t sinit_base, sinit_size;
    1.10 +
    1.11  /*
    1.12   * TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_BASE)
    1.13   */
    1.14 @@ -37,10 +41,33 @@ static const uuid_t tboot_shared_uuid = 
    1.15  
    1.16  extern char __init_begin[], __per_cpu_start[], __per_cpu_end[], __bss_start[];
    1.17  
    1.18 +#define SHA1_SIZE      20
    1.19 +typedef uint8_t   sha1_hash_t[SHA1_SIZE];
    1.20 +
    1.21 +typedef struct __packed {
    1.22 +    uint32_t     version;             /* currently 6 */
    1.23 +    sha1_hash_t  bios_acm_id;
    1.24 +    uint32_t     edx_senter_flags;
    1.25 +    uint64_t     mseg_valid;
    1.26 +    sha1_hash_t  sinit_hash;
    1.27 +    sha1_hash_t  mle_hash;
    1.28 +    sha1_hash_t  stm_hash;
    1.29 +    sha1_hash_t  lcp_policy_hash;
    1.30 +    uint32_t     lcp_policy_control;
    1.31 +    uint32_t     rlp_wakeup_addr;
    1.32 +    uint32_t     reserved;
    1.33 +    uint32_t     num_mdrs;
    1.34 +    uint32_t     mdrs_off;
    1.35 +    uint32_t     num_vtd_dmars;
    1.36 +    uint32_t     vtd_dmars_off;
    1.37 +} sinit_mle_data_t;
    1.38 +
    1.39  void __init tboot_probe(void)
    1.40  {
    1.41      tboot_shared_t *tboot_shared;
    1.42      unsigned long p_tboot_shared;
    1.43 +    uint32_t map_base, map_size;
    1.44 +    unsigned long map_addr;
    1.45  
    1.46      /* Look for valid page-aligned address for shared page. */
    1.47      p_tboot_shared = simple_strtoul(opt_tboot, NULL, 0);
    1.48 @@ -68,6 +95,30 @@ void __init tboot_probe(void)
    1.49      printk("  shutdown_entry: 0x%08x\n", tboot_shared->shutdown_entry);
    1.50      printk("  tboot_base: 0x%08x\n", tboot_shared->tboot_base);
    1.51      printk("  tboot_size: 0x%x\n", tboot_shared->tboot_size);
    1.52 +
    1.53 +    /* these will be needed by tboot_protect_mem_regions() and/or
    1.54 +       tboot_parse_dmar_table(), so get them now */
    1.55 +
    1.56 +    map_base = PFN_DOWN(TXT_PUB_CONFIG_REGS_BASE);
    1.57 +    map_size = PFN_UP(NR_TXT_CONFIG_PAGES * PAGE_SIZE);
    1.58 +    map_addr = (unsigned long)__va(map_base << PAGE_SHIFT);
    1.59 +    if ( map_pages_to_xen(map_addr, map_base, map_size, __PAGE_HYPERVISOR) )
    1.60 +        return;
    1.61 +
    1.62 +    /* TXT Heap */
    1.63 +    txt_heap_base =
    1.64 +        *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_HEAP_BASE);
    1.65 +    txt_heap_size =
    1.66 +        *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_HEAP_SIZE);
    1.67 +
    1.68 +    /* SINIT */
    1.69 +    sinit_base =
    1.70 +        *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_BASE);
    1.71 +    sinit_size =
    1.72 +        *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_SIZE);
    1.73 +
    1.74 +    destroy_xen_mappings((unsigned long)__va(map_base << PAGE_SHIFT),
    1.75 +                         (unsigned long)__va((map_base + map_size) << PAGE_SHIFT));
    1.76  }
    1.77  
    1.78  void tboot_shutdown(uint32_t shutdown_type)
    1.79 @@ -125,33 +176,26 @@ int tboot_in_measured_env(void)
    1.80  
    1.81  int __init tboot_protect_mem_regions(void)
    1.82  {
    1.83 -    uint64_t base, size;
    1.84 -    uint32_t map_base, map_size;
    1.85 -    unsigned long map_addr;
    1.86      int rc;
    1.87  
    1.88      if ( !tboot_in_measured_env() )
    1.89          return 1;
    1.90  
    1.91 -    map_base = PFN_DOWN(TXT_PUB_CONFIG_REGS_BASE);
    1.92 -    map_size = PFN_UP(NR_TXT_CONFIG_PAGES * PAGE_SIZE);
    1.93 -    map_addr = (unsigned long)__va(map_base << PAGE_SHIFT);
    1.94 -    if ( map_pages_to_xen(map_addr, map_base, map_size, __PAGE_HYPERVISOR) )
    1.95 +    /* TXT Heap */
    1.96 +    if ( txt_heap_base == 0 )
    1.97          return 0;
    1.98 -
    1.99 -    /* TXT Heap */
   1.100 -    base = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_HEAP_BASE);
   1.101 -    size = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_HEAP_SIZE);
   1.102      rc = e820_change_range_type(
   1.103 -        &e820, base, base + size, E820_RESERVED, E820_UNUSABLE);
   1.104 +        &e820, txt_heap_base, txt_heap_base + txt_heap_size,
   1.105 +        E820_RESERVED, E820_UNUSABLE);
   1.106      if ( !rc )
   1.107          return 0;
   1.108  
   1.109      /* SINIT */
   1.110 -    base = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_BASE);
   1.111 -    size = *(uint64_t *)__va(TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_SIZE);
   1.112 +    if ( sinit_base == 0 )
   1.113 +        return 0;
   1.114      rc = e820_change_range_type(
   1.115 -        &e820, base, base + size, E820_RESERVED, E820_UNUSABLE);
   1.116 +        &e820, sinit_base, sinit_base + sinit_size,
   1.117 +        E820_RESERVED, E820_UNUSABLE);
   1.118      if ( !rc )
   1.119          return 0;
   1.120  
   1.121 @@ -163,11 +207,61 @@ int __init tboot_protect_mem_regions(voi
   1.122      if ( !rc )
   1.123          return 0;
   1.124  
   1.125 +    return 1;
   1.126 +}
   1.127 +
   1.128 +int __init tboot_parse_dmar_table(acpi_table_handler dmar_handler)
   1.129 +{
   1.130 +    uint32_t map_base, map_size;
   1.131 +    unsigned long map_vaddr;
   1.132 +    void *heap_ptr;
   1.133 +    struct acpi_table_header *dmar_table;
   1.134 +    int rc;
   1.135 +
   1.136 +    if ( !tboot_in_measured_env() )
   1.137 +        return acpi_table_parse(ACPI_SIG_DMAR, dmar_handler);
   1.138 +
   1.139 +    /* ACPI tables may not be DMA protected by tboot, so use DMAR copy */
   1.140 +    /* SINIT saved in SinitMleData in TXT heap (which is DMA protected) */
   1.141 +
   1.142 +    if ( txt_heap_base == 0 )
   1.143 +        return 1;
   1.144 +
   1.145 +    /* map TXT heap into Xen addr space */
   1.146 +    map_base = PFN_DOWN(txt_heap_base);
   1.147 +    map_size = PFN_UP(txt_heap_size);
   1.148 +    map_vaddr = (unsigned long)__va(map_base << PAGE_SHIFT);
   1.149 +    if ( map_pages_to_xen(map_vaddr, map_base, map_size, __PAGE_HYPERVISOR) )
   1.150 +        return 1;
   1.151 +
   1.152 +    /* walk heap to SinitMleData */
   1.153 +    heap_ptr = __va(txt_heap_base);
   1.154 +    /* skip BiosData */
   1.155 +    heap_ptr += *(uint64_t *)heap_ptr;
   1.156 +    /* skip OsMleData */
   1.157 +    heap_ptr += *(uint64_t *)heap_ptr;
   1.158 +    /* skip OsSinitData */
   1.159 +    heap_ptr += *(uint64_t *)heap_ptr;
   1.160 +    /* now points to SinitMleDataSize; set to SinitMleData */
   1.161 +    heap_ptr += sizeof(uint64_t);
   1.162 +    /* get addr of DMAR table */
   1.163 +    dmar_table = (struct acpi_table_header *)(heap_ptr +
   1.164 +            ((sinit_mle_data_t *)heap_ptr)->vtd_dmars_off - sizeof(uint64_t));
   1.165 +
   1.166 +    rc = dmar_handler(dmar_table);
   1.167 +
   1.168      destroy_xen_mappings(
   1.169          (unsigned long)__va(map_base << PAGE_SHIFT),
   1.170          (unsigned long)__va((map_base + map_size) << PAGE_SHIFT));
   1.171 +  
   1.172 +    /* acpi_parse_dmar() zaps APCI DMAR signature in TXT heap table */
   1.173 +    /* but dom0 will read real table, so must zap it there too */
   1.174 +    dmar_table = NULL;
   1.175 +    acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_table);
   1.176 +    if ( dmar_table != NULL )
   1.177 +        ((struct acpi_table_dmar *)dmar_table)->header.signature[0] = '\0';
   1.178  
   1.179 -    return 1;
   1.180 +    return rc;
   1.181  }
   1.182  
   1.183  /*
     2.1 --- a/xen/drivers/passthrough/vtd/dmar.c	Thu Jan 29 12:10:39 2009 +0000
     2.2 +++ b/xen/drivers/passthrough/vtd/dmar.c	Thu Jan 29 12:44:31 2009 +0000
     2.3 @@ -506,6 +506,15 @@ static int __init acpi_parse_dmar(struct
     2.4      return ret;
     2.5  }
     2.6  
     2.7 +#ifdef CONFIG_X86
     2.8 +#include <asm/tboot.h>
     2.9 +/* ACPI tables may not be DMA protected by tboot, so use DMAR copy */
    2.10 +/* SINIT saved in SinitMleData in TXT heap (which is DMA protected) */
    2.11 +#define parse_dmar_table(h) tboot_parse_dmar_table(h)
    2.12 +#else
    2.13 +#define parse_dmar_table(h) acpi_table_parse(ACPI_SIG_DMAR, h)
    2.14 +#endif
    2.15 +
    2.16  int acpi_dmar_init(void)
    2.17  {
    2.18      int rc;
    2.19 @@ -519,7 +528,7 @@ int acpi_dmar_init(void)
    2.20      if ( !iommu_enabled )
    2.21          goto fail;
    2.22  
    2.23 -    rc = acpi_table_parse(ACPI_SIG_DMAR, acpi_parse_dmar);
    2.24 +    rc = parse_dmar_table(acpi_parse_dmar);
    2.25      if ( rc )
    2.26          goto fail;
    2.27  
     3.1 --- a/xen/include/asm-x86/tboot.h	Thu Jan 29 12:10:39 2009 +0000
     3.2 +++ b/xen/include/asm-x86/tboot.h	Thu Jan 29 12:44:31 2009 +0000
     3.3 @@ -37,6 +37,8 @@
     3.4  #ifndef __TBOOT_H__
     3.5  #define __TBOOT_H__
     3.6  
     3.7 +#include <xen/acpi.h>
     3.8 +
     3.9  #ifndef __packed
    3.10  #define __packed   __attribute__ ((packed))
    3.11  #endif
    3.12 @@ -110,6 +112,7 @@ void tboot_probe(void);
    3.13  void tboot_shutdown(uint32_t shutdown_type);
    3.14  int tboot_in_measured_env(void);
    3.15  int tboot_protect_mem_regions(void);
    3.16 +int tboot_parse_dmar_table(acpi_table_handler dmar_handler);
    3.17  
    3.18  #endif /* __TBOOT_H__ */
    3.19