diff options
-rw-r--r-- | xen/arch/x86/Makefile | 1 | ||||
-rw-r--r-- | xen/arch/x86/acpi/power.c | 51 | ||||
-rw-r--r-- | xen/arch/x86/boot/cmdline.S | 8 | ||||
-rw-r--r-- | xen/arch/x86/domain_build.c | 14 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmcs.c | 8 | ||||
-rw-r--r-- | xen/arch/x86/setup.c | 3 | ||||
-rw-r--r-- | xen/arch/x86/shutdown.c | 14 | ||||
-rw-r--r-- | xen/arch/x86/tboot.c | 70 | ||||
-rw-r--r-- | xen/include/asm-x86/fixmap.h | 1 | ||||
-rw-r--r-- | xen/include/asm-x86/tboot.h | 90 |
10 files changed, 250 insertions, 10 deletions
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index aa4f42ffd1..d61514b0a3 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -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 diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c index f14fda92fb..7a24e35d2a 100644 --- a/xen/arch/x86/acpi/power.c +++ b/xen/arch/x86/acpi/power.c @@ -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); diff --git a/xen/arch/x86/boot/cmdline.S b/xen/arch/x86/boot/cmdline.S index 3e7476d550..babcece48c 100644 --- a/xen/arch/x86/boot/cmdline.S +++ b/xen/arch/x86/boot/cmdline.S @@ -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: diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 0fe3b2adc5..637a29f3c3 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -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); diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 96b2ca6b6d..304eea48f1 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -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)); diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 1555f58941..733ff2974a 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -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); diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c index c66c3fa019..760b260bc2 100644 --- a/xen/arch/x86/shutdown.c +++ b/xen/arch/x86/shutdown.c @@ -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 index 0000000000..dbc9b8e407 --- /dev/null +++ b/xen/arch/x86/tboot.c @@ -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); +} diff --git a/xen/include/asm-x86/fixmap.h b/xen/include/asm-x86/fixmap.h index 172f6d18eb..644c9ff53c 100644 --- a/xen/include/asm-x86/fixmap.h +++ b/xen/include/asm-x86/fixmap.h @@ -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 index 0000000000..3393b57aed --- /dev/null +++ b/xen/include/asm-x86/tboot.h @@ -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: + */ |