]> xenbits.xensource.com Git - xen.git/commitdiff
Intel(R) Trusted Execution Technology (Intel(R) TXT) support for Xen.
authorKeir Fraser <keir@xensource.com>
Tue, 30 Oct 2007 10:13:43 +0000 (10:13 +0000)
committerKeir Fraser <keir@xensource.com>
Tue, 30 Oct 2007 10:13:43 +0000 (10:13 +0000)
Signed-off-by: Joseph Cihula <joseph.cihula@intel.com>
xen/arch/x86/Makefile
xen/arch/x86/acpi/power.c
xen/arch/x86/boot/cmdline.S
xen/arch/x86/domain_build.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/setup.c
xen/arch/x86/shutdown.c
xen/arch/x86/tboot.c [new file with mode: 0644]
xen/include/asm-x86/fixmap.h
xen/include/asm-x86/tboot.h [new file with mode: 0644]

index aa4f42ffd19dadd0c7a03edc44df087fe07bf70a..d61514b0a33170f4424352517dd50e5d5d8b34ab 100644 (file)
@@ -46,6 +46,7 @@ obj-y += usercopy.o
 obj-y += x86_emulate.o
 obj-y += machine_kexec.o
 obj-y += crash.o
+obj-y += tboot.o
 
 obj-$(crash_debug) += gdbstub.o
 
index f14fda92fb8383b9843475d06bc0b54bce9426dc..7a24e35d2a6dde1c1775a460e1f15e48ca7fd42b 100644 (file)
@@ -25,6 +25,7 @@
 #include <xen/domain.h>
 #include <xen/console.h>
 #include <public/platform.h>
+#include <asm/tboot.h>
 
 #define pmprintk(_l, _f, _a...) printk(_l "<PM> " _f "\n", ## _a )
 
@@ -94,11 +95,19 @@ static void acpi_sleep_prepare(u32 state)
     wakeup_vector_va = __acpi_map_table(
         acpi_sinfo.wakeup_vector, sizeof(uint64_t));
     if ( acpi_sinfo.vector_width == 32 )
-        *(uint32_t *)wakeup_vector_va =
-            (uint32_t)bootsym_phys(wakeup_start);
+    {
+            *(uint32_t *)wakeup_vector_va =
+                tboot_in_measured_env() ?
+                (uint32_t)g_tboot_shared->s3_tb_wakeup_entry :
+                (uint32_t)bootsym_phys(wakeup_start);
+    }
     else
-        *(uint64_t *)wakeup_vector_va =
-            (uint64_t)bootsym_phys(wakeup_start);
+    {
+            *(uint64_t *)wakeup_vector_va =
+                tboot_in_measured_env() ?
+                (uint64_t)g_tboot_shared->s3_tb_wakeup_entry :
+               (uint64_t)bootsym_phys(wakeup_start);
+    }
 }
 
 static void acpi_sleep_post(u32 state) {}
@@ -221,9 +230,43 @@ static int acpi_get_wake_status(void)
     return val;
 }
 
+static void tboot_sleep(u8 sleep_state)
+{
+   uint32_t shutdown_type;
+   
+   *((struct acpi_sleep_info *)(unsigned long)g_tboot_shared->acpi_sinfo) =
+       acpi_sinfo;
+
+   switch ( sleep_state )
+   {
+       case ACPI_STATE_S3:
+           shutdown_type = TB_SHUTDOWN_S3;
+           g_tboot_shared->s3_k_wakeup_entry =
+              (uint32_t)bootsym_phys(wakeup_start);
+           break;
+       case ACPI_STATE_S4:
+           shutdown_type = TB_SHUTDOWN_S4;
+           break;
+       case ACPI_STATE_S5:
+           shutdown_type = TB_SHUTDOWN_S5;
+           break;
+       default:
+           return;
+   }
+
+   tboot_shutdown(shutdown_type);
+}
+         
 /* System is really put into sleep state by this stub */
 acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
 {
+    if ( tboot_in_measured_env() )
+    {
+        tboot_sleep(sleep_state);
+        pmprintk(XENLOG_ERR, "TBOOT failed entering s3 state\n");
+        return_ACPI_STATUS(AE_ERROR);
+    }
+
     ACPI_FLUSH_CPU_CACHE();
 
     outw((u16)acpi_sinfo.pm1a_cnt_val, acpi_sinfo.pm1a_cnt);
index 3e7476d550894596e5d8148791e4db82c2e090f1..babcece48ceaa7daff8febb0bec60d67cf88ce9f 100644 (file)
@@ -170,6 +170,12 @@ cmdline_parse_early:
         test    %eax,%eax
         setnz   bootsym_phys(skip_realmode)
 
+        /* Check for 'tboot=' command-line option. */
+        movl    $sym_phys(.Ltboot_opt),4(%esp)
+        call    .Lfind_option
+        test    %eax,%eax
+        setnz   bootsym_phys(skip_realmode) /* tboot= implies no-real-mode */
+
 .Lparse_edd:
         /* Check for 'edd=' command-line option. */
         movl    $sym_phys(.Ledd_opt),4(%esp)
@@ -346,6 +352,8 @@ cmdline_parse_early:
         .asciz  "current"
 .Lno_rm_opt:
         .asciz  "no-real-mode"
+.Ltboot_opt:
+        .asciz  "tboot"
 .Ledid_opt:
         .asciz  "edid"
 .Ledid_force:
index 0fe3b2adc53a579a57619f15e628c2345909b6c5..637a29f3c3284427ce0a09e22242809636eaa583 100644 (file)
@@ -990,14 +990,16 @@ int __init construct_dom0(
             rc |= iomem_deny_access(dom0, mfn, mfn);
     }
 
-    /* Remove access to E820_UNUSABLE I/O regions. */
+    /* Remove access to E820_UNUSABLE I/O regions above 1MB. */
     for ( i = 0; i < e820.nr_map; i++ )
     {
-        if ( e820.map[i].type != E820_UNUSABLE)
-            continue;
-        mfn = paddr_to_pfn(e820.map[i].addr);
-        nr_pages = (e820.map[i].size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-        rc |= iomem_deny_access(dom0, mfn, mfn + nr_pages - 1);
+        unsigned long sfn, efn;
+        sfn = max_t(unsigned long, paddr_to_pfn(e820.map[i].addr), 0x100ul);
+        efn = paddr_to_pfn(e820.map[i].addr + e820.map[i].size - 1);
+        if ( (e820.map[i].type == E820_UNUSABLE) &&
+             (e820.map[i].size != 0) &&
+             (sfn <= efn) )
+            rc |= iomem_deny_access(dom0, sfn, efn);
     }
 
     BUG_ON(rc != 0);
index 96b2ca6b6d3a3e592810227ecaae75260d65dd29..304eea48f19a124e199aa51955e1edad0b002ca0 100644 (file)
@@ -36,6 +36,7 @@
 #include <xen/kernel.h>
 #include <xen/keyhandler.h>
 #include <asm/shadow.h>
+#include <asm/tboot.h>
 
 /* Dynamic (run-time adjusted) execution control flags. */
 u32 vmx_pin_based_exec_control __read_mostly;
@@ -277,6 +278,13 @@ int vmx_cpu_up(void)
         wrmsr(IA32_FEATURE_CONTROL_MSR, eax, 0);
     }
 
+    if ( !tboot_in_measured_env() &&
+         !(eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON_OUTSIDE_SMX) )
+    {
+        printk("VMX only allowed in SMX but SMX not active.\n");
+        return 0;
+    }
+
     vmx_init_vmcs_config();
 
     INIT_LIST_HEAD(&this_cpu(active_vmcs_list));
index 1555f589415ed1a219ecf574b3909637ad0c0f72..733ff2974a0c7b4785659ff564d9da731e239a45 100644 (file)
@@ -37,6 +37,7 @@
 #include <xen/kexec.h>
 #include <asm/edd.h>
 #include <xsm/xsm.h>
+#include <asm/tboot.h>
 
 #if defined(CONFIG_X86_64)
 #define BOOTSTRAP_DIRECTMAP_END (1UL << 32) /* 4GB */
@@ -846,6 +847,8 @@ void __init __start_xen(unsigned long mbi_p)
 
     paging_init();
 
+    tboot_probe();
+
     /* Unmap the first page of CPU0's stack. */
     memguard_guard_stack(cpu0_stack);
 
index c66c3fa019ce98c81a3a40476f38736cc387d884..760b260bc29266437dab7c91362e13714825cd8f 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mpspec.h>
+#include <asm/tboot.h>
 
 /* reboot_str: comma-separated list of reboot options. */
 static char __initdata reboot_str[10] = "";
@@ -219,6 +220,9 @@ void machine_restart(void)
 
     smp_send_stop();
 
+    if ( tboot_in_measured_env() )
+        tboot_shutdown(TB_SHUTDOWN_REBOOT);
+
     /* Rebooting needs to touch the page at absolute address 0. */
     *((unsigned short *)__va(0x472)) = reboot_mode;
 
@@ -328,3 +332,13 @@ static int __init reboot_init(void)
     return 0;
 }
 __initcall(reboot_init);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c
new file mode 100644 (file)
index 0000000..dbc9b8e
--- /dev/null
@@ -0,0 +1,70 @@
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <asm/fixmap.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/tboot.h>
+
+/* tboot=<physical address of shared page> */
+static char opt_tboot[20] = "";
+string_param("tboot", opt_tboot);
+
+/* Global pointer to shared data; NULL means no measured launch. */
+tboot_shared_t *g_tboot_shared;
+
+static const uuid_t tboot_shared_uuid = TBOOT_SHARED_UUID;
+
+void __init tboot_probe(void)
+{
+    tboot_shared_t *tboot_shared;
+    unsigned long p_tboot_shared;
+
+    /* Look for valid page-aligned address for shared page. */
+    p_tboot_shared = simple_strtoul(opt_tboot, NULL, 0);
+    if ( (p_tboot_shared == 0) || ((p_tboot_shared & ~PAGE_MASK) != 0) )
+        return;
+
+    /* Map and check for tboot UUID. */
+    set_fixmap(FIX_TBOOT_SHARED_BASE, p_tboot_shared);
+    tboot_shared = (tboot_shared_t *)fix_to_virt(FIX_TBOOT_SHARED_BASE);
+    if ( memcmp(&tboot_shared_uuid, (uuid_t *)tboot_shared, sizeof(uuid_t)) )
+        return;
+
+    g_tboot_shared = tboot_shared;
+    printk("TBOOT: found shared page at phys addr %lx:\n", p_tboot_shared);
+    printk("  version: %d\n", tboot_shared->version);
+    printk("  log_addr: 0x%08x\n", tboot_shared->log_addr);
+    printk("  shutdown_entry32: 0x%08x\n", tboot_shared->shutdown_entry32);
+    printk("  shutdown_entry64: 0x%08x\n", tboot_shared->shutdown_entry64);
+    printk("  shutdown_type: %d\n", tboot_shared->shutdown_type);
+    printk("  s3_tb_wakeup_entry: 0x%08x\n", tboot_shared->s3_tb_wakeup_entry);
+    printk("  s3_k_wakeup_entry: 0x%08x\n", tboot_shared->s3_k_wakeup_entry);
+    printk("  &acpi_sinfo: 0x%p\n", &tboot_shared->acpi_sinfo);
+}
+
+void tboot_shutdown(uint32_t shutdown_type)
+{
+    g_tboot_shared->shutdown_type = shutdown_type;
+
+    local_irq_disable();
+
+    /* Create identity map for 0-640k to include tboot code. */
+    map_pages_to_xen(0, 0, PFN_UP(0xa0000), __PAGE_HYPERVISOR);
+    write_ptbase(idle_vcpu[0]);
+
+#ifdef __x86_64__
+    asm volatile ( "call *%%rdi" :: "D" (g_tboot_shared->shutdown_entry64) );
+#else
+    asm volatile ( "call *%0" :: "r" (g_tboot_shared->shutdown_entry32) );
+#endif
+
+    BUG(); /* should not reach here */
+}
+
+int tboot_in_measured_env(void)
+{
+    return (g_tboot_shared != NULL);
+}
index 172f6d18eb169ead35ab57022eb4a5a7105a6466..644c9ff53c774ce7b074aea6cb04a06ee1f46c8a 100644 (file)
@@ -46,6 +46,7 @@ enum fixed_addresses {
     FIX_IOMMU_REGS_END = FIX_IOMMU_REGS_BASE_0 + MAX_IOMMUS-1,
     FIX_IOMMU_MMIO_BASE_0,
     FIX_IOMMU_MMIO_END = FIX_IOMMU_MMIO_BASE_0 + IOMMU_PAGES -1,
+    FIX_TBOOT_SHARED_BASE,
     __end_of_fixed_addresses
 };
 
diff --git a/xen/include/asm-x86/tboot.h b/xen/include/asm-x86/tboot.h
new file mode 100644 (file)
index 0000000..3393b57
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * tboot.h: shared data structure with MLE and kernel and functions
+ *          used by kernel for runtime support
+ *
+ * Copyright (c) 2006-2007, 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 __TBOOT_H__
+#define __TBOOT_H__
+
+typedef struct __attribute__ ((__packed__)) {
+  uint32_t    data1;
+  uint16_t    data2;
+  uint16_t    data3;
+  uint16_t    data4;
+  uint8_t     data5[6];
+} uuid_t;
+
+/* used to communicate between tboot and the launched kernel (i.e. Xen) */
+#define MAX_TB_ACPI_SINFO_SIZE   64
+
+typedef struct __attribute__ ((__packed__)) {
+    uuid_t    uuid;              /* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */
+    uint32_t  version;           /* 0x01 */
+    uint32_t  log_addr;          /* physical addr of tb_log_t log */
+    uint32_t  shutdown_entry32;  /* entry point for tboot shutdown from 32b */
+    uint32_t  shutdown_entry64;  /* entry point for tboot shutdown from 64b */
+    uint32_t  shutdown_type;     /* type of shutdown (TB_SHUTDOWN_*) */
+    uint32_t  s3_tb_wakeup_entry;/* entry point for tboot s3 wake up */
+    uint32_t  s3_k_wakeup_entry; /* entry point for xen s3 wake up */
+    uint8_t   acpi_sinfo[MAX_TB_ACPI_SINFO_SIZE];
+                                 /* where kernel put acpi sleep info in Sx */
+} tboot_shared_t;
+
+#define TB_SHUTDOWN_REBOOT      0
+#define TB_SHUTDOWN_S5          1
+#define TB_SHUTDOWN_S4          2
+#define TB_SHUTDOWN_S3          3
+#define TB_SHUTDOWN_HALT        4
+
+/* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */
+#define TBOOT_SHARED_UUID    { 0x663c8dff, 0xe8b3, 0x4b82, 0xaabf, \
+                               { 0x19, 0xea, 0x4d, 0x5, 0x7a, 0x8 } };
+
+extern tboot_shared_t *g_tboot_shared;
+
+void tboot_probe(void);
+void tboot_shutdown(uint32_t shutdown_type);
+int tboot_in_measured_env(void);
+
+#endif /* __TBOOT_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */