All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Xense-devel] [RFC][PATCH][UPDATED] Intel(R) LaGrande Technology support
@ 2007-04-12 21:07 Jonathan M. McCune
  2007-04-12 21:52 ` Cihula, Joseph
  2007-07-11 20:51 ` [RFC][PATCH][0/2] Intel(r) Trusted Execution Technology Jonathan M. McCune
  0 siblings, 2 replies; 6+ messages in thread
From: Jonathan M. McCune @ 2007-04-12 21:07 UTC (permalink / raw)
  To: xense-devel, xen-devel; +Cc: leendert, joseph.cihula, Stefan Berger

Hello,

Has any more work been done on this front?  The message below is
from Sept. 2006.  In particular, the LT/TXT Technology Enabling
Platform (TEP) is now available from MPC Corp.  Where can one
obtain an appropriate AC SINIT module (i.e., like
lpg_sinit_20050831_pae.auth.bin below)?  I would like to begin
using Xen with TXT support.

Thanks,
-Jon




This patch adds SMP support to the previous version.  Since that has not
been merged I have included it in this patch.  This should apply cleanly
to the tip.  Below is the text of the original submittal, slightly
updated.

Attached is a preliminary patch that adds Intel(R) LaGrande Technology
(LT) (Safer Mode Extensions - SMX) support to Xen.  While there are
still several enhancements needed for complete support, we feel that it
is sufficiently complete for an initial public posting to expose to the
community.


LaGrande Technology in Brief:
-----------------------------
o  Provides dynamic root of trust for measurement (DRTM)
o  DMA protection
o  Data protection in case of improper shutdown

For more information on LT, see the Intel LaGrande Technology website:
http://www.intel.com/technology/security/.
This site also has a link to the LT preliminary specification (an
updated version that reflects the functionlaity of this code will be
available later this week).


The LT functionality this code adds is:
---------------------------------------
o  Measured Launch.  If the processor is detected as being LT-capable
and enabled then the code will attempt to perform a measured launch.  If
the processor is (not capable) or (capable but not enabled) or (capable
and enabled but the launch process fails (missing SINIT, corrupted data,
etc.)) then it will fall-through to a non-LT boot.
o  Teardown of measured environment.  When Xen exits the LT environment
will be torn down properly.
o  Reset data protection.  LT HW prevents access to secrets if the
system is reset without clearing them from memory (as part of a LT
teardown).  This code will support this by setting the flag indicating
that memory should be so protected during the measured launch and
clearing the flag just before teardown.
o  Protection of LT memory ranges.  LT reserves certain regions of RAM
for its use and also defines several MMIO regions.  These regions are
protected from use by any domains (including dom0).  Note that there a
sub-regions of the MMIO space that are left accessible to dom0 (LT
public configuration space, TPM localities 0,1).


Patch breakdown:
----------------
Config.mk - add INTEL_SMX build config
xen/Rules.mk - adds '-DCONFIG_SMX' compile flag if INTEL_SMX=y
xen/arch/x86/Makefile - add arch/x86/smx dir to build
xen/arch/x86/boot/x86_32.S - hook startup to launch LT
environmentxen/arch/x86/setup.c - initialize fixmap entries for LT
config reg space
xen/arch/x86/domain_build.c - protect LT private config space
xen/arch/x86/e820.c - support for E820_PROTECTED mem type
xen/arch/x86/hvm/vmx/vmx.c - support new LT/VMX IA32_FEATURE_CONTROL_MSR
flag
xen/arch/x86/mm.c - support for E820_PROTECTED mem type
xen/arch/x86/setup.c - hook to reserve LT RAM regions and initialize
fixmap entries for LT config reg space
xen/arch/x86/shutdown.c - hook shutdown to teardown LT environment
xen/common/domctl.c - prevent XEN_DOMCTL_iomem_permission from being
able to map LT private config space
xen/include/asm-x86/cpufeature.h - adds new SMX feature flag
xen/include/asm-x86/e820.h - export print_e820_memory_map()
xen/include/asm-x86/fixmap.h - adds fixmap entries for LT config reg
space
xen/include/asm-x86/msr.h - adds new VMX and SMX MSR flags
xen/include/asm-x86/processor.h - adds new CR4 SMX flag
xen/include/public/hvm/e820.h - add E820_PROTECTED mem type
xen/arch/x86/smx/Makefile - self explanatory
xen/arch/x86/smx/acmod.c - LT Authenticated Code (AC) module support fns
xen/arch/x86/smx/early_printk.c - serial printk() for early in boot
process
xen/arch/x86/smx/errors.c - error parsing/display fns
xen/arch/x86/smx/mtrrs.c - MTRR handling for AC module launch
xen/arch/x86/smx/smx.c - main LT/SMX fns and entry points
xen/arch/x86/smx/tpm.c - basic TPM support fns
xen/include/asm-x86/smx/* - headers for SMX/LT fns


This code has been developed and tested on Intel Software Development
Platform (SDP) 3 systems (available under NDA via the Intel Premier
Support channel).  It will be updated to work with the LT Technology
Enabling Platform (TEP) that will be publicly available this fall.


Instructions for use:
---------------------
o  By default, the functionality is disabled in the build.  It can be
enabled by changing the INTEL_SMX flag to 'y' in Config.mk.
o  The SINIT AC module (available with SDP3 systems) must be added to
the grub.conf boot config as the last module, e.g.:
        ...
        module /initrd-2.6.16.13-xen.img
        module /lpg_sinit_20050831_pae.auth.bin
o  Progress of the LT launch process is indicated via debug printk's to
COM1 (hardcoded).  These appear before the normal "(XEN)" output and are
prefixed by "SMX:".  The code (in early_printk.c) does not initialize
the COM port so this needs to be done by GRUB - grub.conf should have:
        serial --speed=115200 --unit=0
        terminal console serial


Caveats / Notes:
----------------
o  x86_64 is not supported yet (IA64 does not support LT at this time).
o  The code only measures the hypervisor (and its command line), which
is not the complete TCB.
o  It doesn't cap (extend with invalid value) the dynamic TPM PCRs when
the LT environment is torn down.  Instead it disables the BIOS reboot
option so that any shutdown/reboot will have to reset the platform and
the TPM.
o  TPM locality 2 is not protected.  The defined behavior for access to
unpermitted localities is for reads to return 0xff's and writes to be
dropped.  This will require mapping pages from locality 3 or 4 into the
locality 2 range.
o  No DMA protection has been implemented in this patch.  SDP3 only
supports the NoDMA table for DMA protection and this will be superseded
by VT-d.  VT-d support for LT will be added after it is added for the
general case.

These limitations will be addressed in subsequent patches.

There was a presentation on the code at the Xen Summit.  More
information on LT is available at
http://www.intel.com/technology/security/.  Comments and feedback are
welcome at any time.


Joseph Cihula
(Linux) Software Security Architect
Open Source Technology Center
Intel Corp.

*** These opinions are not necessarily those of my employer ***

^ permalink raw reply	[flat|nested] 6+ messages in thread
* [RFC][PATCH][UPDATED] Intel(R) LaGrande Technology support
@ 2006-09-22 19:00 Cihula, Joseph
  2006-09-23 17:01 ` [Xense-devel] " Leendert Van Doorn
  0 siblings, 1 reply; 6+ messages in thread
From: Cihula, Joseph @ 2006-09-22 19:00 UTC (permalink / raw)
  To: xen-devel, xense-devel

[-- Attachment #1: Type: text/plain, Size: 6267 bytes --]

This patch adds SMP support to the previous version.  Since that has not
been merged I have included it in this patch.  This should apply cleanly
to the tip.  Below is the text of the original submittal, slightly
updated.

Attached is a preliminary patch that adds Intel(R) LaGrande Technology
(LT) (Safer Mode Extensions - SMX) support to Xen.  While there are
still several enhancements needed for complete support, we feel that it
is sufficiently complete for an initial public posting to expose to the
community.


LaGrande Technology in Brief:
-----------------------------
o  Provides dynamic root of trust for measurement (DRTM)
o  DMA protection
o  Data protection in case of improper shutdown

For more information on LT, see the Intel LaGrande Technology website:
http://www.intel.com/technology/security/.
This site also has a link to the LT preliminary specification (an
updated version that reflects the functionlaity of this code will be
available later this week).


The LT functionality this code adds is:
---------------------------------------
o  Measured Launch.  If the processor is detected as being LT-capable
and enabled then the code will attempt to perform a measured launch.  If
the processor is (not capable) or (capable but not enabled) or (capable
and enabled but the launch process fails (missing SINIT, corrupted data,
etc.)) then it will fall-through to a non-LT boot.
o  Teardown of measured environment.  When Xen exits the LT environment
will be torn down properly.
o  Reset data protection.  LT HW prevents access to secrets if the
system is reset without clearing them from memory (as part of a LT
teardown).  This code will support this by setting the flag indicating
that memory should be so protected during the measured launch and
clearing the flag just before teardown.
o  Protection of LT memory ranges.  LT reserves certain regions of RAM
for its use and also defines several MMIO regions.  These regions are
protected from use by any domains (including dom0).  Note that there a
sub-regions of the MMIO space that are left accessible to dom0 (LT
public configuration space, TPM localities 0,1).


Patch breakdown:
----------------
Config.mk - add INTEL_SMX build config
xen/Rules.mk - adds '-DCONFIG_SMX' compile flag if INTEL_SMX=y
xen/arch/x86/Makefile - add arch/x86/smx dir to build
xen/arch/x86/boot/x86_32.S - hook startup to launch LT
environmentxen/arch/x86/setup.c - initialize fixmap entries for LT
config reg space
xen/arch/x86/domain_build.c - protect LT private config space
xen/arch/x86/e820.c - support for E820_PROTECTED mem type
xen/arch/x86/hvm/vmx/vmx.c - support new LT/VMX IA32_FEATURE_CONTROL_MSR
flag
xen/arch/x86/mm.c - support for E820_PROTECTED mem type
xen/arch/x86/setup.c - hook to reserve LT RAM regions and initialize
fixmap entries for LT config reg space
xen/arch/x86/shutdown.c - hook shutdown to teardown LT environment
xen/common/domctl.c - prevent XEN_DOMCTL_iomem_permission from being
able to map LT private config space
xen/include/asm-x86/cpufeature.h - adds new SMX feature flag
xen/include/asm-x86/e820.h - export print_e820_memory_map()
xen/include/asm-x86/fixmap.h - adds fixmap entries for LT config reg
space
xen/include/asm-x86/msr.h - adds new VMX and SMX MSR flags
xen/include/asm-x86/processor.h - adds new CR4 SMX flag
xen/include/public/hvm/e820.h - add E820_PROTECTED mem type
xen/arch/x86/smx/Makefile - self explanatory
xen/arch/x86/smx/acmod.c - LT Authenticated Code (AC) module support fns
xen/arch/x86/smx/early_printk.c - serial printk() for early in boot
process
xen/arch/x86/smx/errors.c - error parsing/display fns
xen/arch/x86/smx/mtrrs.c - MTRR handling for AC module launch
xen/arch/x86/smx/smx.c - main LT/SMX fns and entry points
xen/arch/x86/smx/tpm.c - basic TPM support fns
xen/include/asm-x86/smx/* - headers for SMX/LT fns


This code has been developed and tested on Intel Software Development
Platform (SDP) 3 systems (available under NDA via the Intel Premier
Support channel).  It will be updated to work with the LT Technology
Enabling Platform (TEP) that will be publicly available this fall.


Instructions for use:
---------------------
o  By default, the functionality is disabled in the build.  It can be
enabled by changing the INTEL_SMX flag to 'y' in Config.mk.
o  The SINIT AC module (available with SDP3 systems) must be added to
the grub.conf boot config as the last module, e.g.:
	...
	module /initrd-2.6.16.13-xen.img
	module /lpg_sinit_20050831_pae.auth.bin
o  Progress of the LT launch process is indicated via debug printk's to
COM1 (hardcoded).  These appear before the normal "(XEN)" output and are
prefixed by "SMX:".  The code (in early_printk.c) does not initialize
the COM port so this needs to be done by GRUB - grub.conf should have:
	serial --speed=115200 --unit=0
	terminal console serial


Caveats / Notes:
----------------
o  x86_64 is not supported yet (IA64 does not support LT at this time).
o  The code only measures the hypervisor (and its command line), which
is not the complete TCB.
o  It doesn't cap (extend with invalid value) the dynamic TPM PCRs when
the LT environment is torn down.  Instead it disables the BIOS reboot
option so that any shutdown/reboot will have to reset the platform and
the TPM.
o  TPM locality 2 is not protected.  The defined behavior for access to
unpermitted localities is for reads to return 0xff's and writes to be
dropped.  This will require mapping pages from locality 3 or 4 into the
locality 2 range.
o  No DMA protection has been implemented in this patch.  SDP3 only
supports the NoDMA table for DMA protection and this will be superseded
by VT-d.  VT-d support for LT will be added after it is added for the
general case.

These limitations will be addressed in subsequent patches.

There was a presentation on the code at the Xen Summit.  More
information on LT is available at
http://www.intel.com/technology/security/.  Comments and feedback are
welcome at any time.


Joseph Cihula
(Linux) Software Security Architect
Open Source Technology Center
Intel Corp.

*** These opinions are not necessarily those of my employer ***


[-- Attachment #2: intel_lagrande_tech_smp.patch --]
[-- Type: application/octet-stream, Size: 116160 bytes --]

# HG changeset patch
# User root@jcihula-lt32.bj.intel.com
# Date 1158811157 -28800
# Node ID 0b39e8a32d1f15b910285dbe8d4b258d38424a77
# Parent  041be3f6b38e05f904d240630c18cadb1259317b
Adds Intel(R) LaGrande Technology (LT) Safer Mode Extensions (SMX) support

Signed-off-by: Joseph Cihula <joseph.cihula@intel.com>
Signed-off-by: Burzin Daruwala <burzin.daruwala@intel.com>

diff -r 041be3f6b38e -r 0b39e8a32d1f Config.mk
--- a/Config.mk	Tue Sep 19 14:26:47 2006 +0100
+++ b/Config.mk	Thu Sep 21 11:59:17 2006 +0800
@@ -7,6 +7,13 @@ XEN_COMPILE_ARCH    ?= $(shell uname -m 
                                               -e s/ppc/powerpc/)
 XEN_TARGET_ARCH     ?= $(XEN_COMPILE_ARCH)
 XEN_TARGET_X86_PAE  ?= n
+
+# LaGrande Technology (LT) Safer Mode Extensions (SMX)
+INTEL_SMX ?= n
+# TBD: fix for x86_64
+ifeq ($(x86_64),y)
+INTEL_SMX := n
+endif
 
 # Tools to run on system hosting the build
 HOSTCC     = gcc
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/Rules.mk
--- a/xen/Rules.mk	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/Rules.mk	Thu Sep 21 11:59:17 2006 +0800
@@ -57,6 +57,7 @@ CFLAGS-$(crash_debug)  += -DCRASH_DEBUG
 CFLAGS-$(crash_debug)  += -DCRASH_DEBUG
 CFLAGS-$(perfc)        += -DPERF_COUNTERS
 CFLAGS-$(perfc_arrays) += -DPERF_ARRAYS
+CFLAGS-$(INTEL_SMX)    += -DCONFIG_SMX
 
 ifneq ($(max_phys_cpus),)
 CFLAGS-y               += -DMAX_PHYS_CPUS=$(max_phys_cpus)
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/Makefile	Thu Sep 21 11:59:17 2006 +0800
@@ -2,6 +2,7 @@ subdir-y += cpu
 subdir-y += cpu
 subdir-y += genapic
 subdir-y += hvm
+subdir-$(INTEL_SMX) += smx
 subdir-y += mm
 subdir-y += oprofile
 
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/boot/x86_32.S
--- a/xen/arch/x86/boot/x86_32.S	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/boot/x86_32.S	Thu Sep 21 11:59:17 2006 +0800
@@ -9,6 +9,11 @@
                 
         .text
 
+#ifdef CONFIG_SMX
+        .global __start
+        .global _smx_wakeup
+#endif
+	
 ENTRY(start)
 ENTRY(stext)
 ENTRY(_stext)
@@ -43,7 +48,30 @@ 3:      in      %dx,%al
         mov     $7,%al
         stosb                  # Write an attribute to the VGA framebuffer
         jmp     1b
-        
+
+#ifdef CONFIG_SMX
+/*
+ * entry point for GETSEC[WAKEUP]
+ */
+_smx_wakeup:
+	# get initial APIC ID for this processor
+	mov	$0x01,%eax
+	xor	%ebx,%ebx
+	cpuid
+	shr	$24,%ebx
+	and	$0xff,%ebx
+
+	/* wait for BSP to set _smp_resume w/ cpu # to bring up */
+spin_restart:
+	pause
+	cmp	%ebx,(_smp_resume-__PAGE_OFFSET)
+	jne	spin_restart
+
+	movl	$0xA5A5A5A5, %ebx # Flag an SMP trampoline
+
+	jmp	__start
+#endif
+		
 __start:
         /* Set up a few descriptors: on entry only CS is guaranteed good. */
         lgdt    %cs:nopaging_gdt_descr-__PAGE_OFFSET
@@ -71,7 +99,16 @@ 1:      lss     stack_start-__PAGE_OFFSE
 
         cmp     $(SECONDARY_CPU_FLAG),%ebx
         je      start_paging
-                
+
+#ifdef CONFIG_SMX
+	/* if this is a re-start due to SENTER then eax was cleared, so */
+	/* set it back */
+	cmp	$0x01,(_senter_start-__PAGE_OFFSET)
+	jne	skip_set
+	mov	$0x2BADB002,%eax
+
+skip_set:
+#endif
         /* Check for Multiboot bootloader */
         cmp     $0x2BADB002,%eax
         jne     not_multiboot
@@ -86,6 +123,16 @@ 1:      lss     stack_start-__PAGE_OFFSE
         /* Save the Multiboot info structure for later use. */
         add     $__PAGE_OFFSET,%ebx
         push    %ebx
+
+#ifdef CONFIG_SMX
+        /* call measured launch code */
+        call   start_smx
+
+        /* after SENTER, ebx is cleared, so start_smx returns saved value */
+        /* which we move back to ebx */
+        mov     %eax,%ebx
+        push    %ebx
+#endif
 
 #ifdef CONFIG_X86_PAE
         /* Initialize low and high mappings of all memory with 2MB pages */
@@ -200,7 +247,7 @@ ENTRY(stack_start)
 .globl gdt        
 
         ALIGN
-        
+
         .word   0    
 idt_descr:
         .word   256*8-1
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/domain_build.c	Thu Sep 21 11:59:17 2006 +0800
@@ -26,6 +26,10 @@
 #include <asm/desc.h>
 #include <asm/i387.h>
 #include <asm/shadow.h>
+#ifdef CONFIG_SMX
+#include <asm/smx/smx.h>
+#include <asm/smx/config_regs.h>
+#endif
 
 #include <public/version.h>
 #include <public/elfnote.h>
@@ -848,6 +852,25 @@ int construct_dom0(struct domain *d,
             rc |= iomem_deny_access(dom0, mfn, mfn);
     }
 
+#ifdef CONFIG_SMX
+    if ( smx_in_prot_env() ) {
+        /*
+         * remove permissions for LT private config register space and
+         * all of LT device memory except TPM localities 0,1
+         */
+        
+        /* private config regs */
+        mfn = paddr_to_pfn(LT_PRIV_CONFIG_REGS_BASE);
+        rc |= iomem_deny_access(dom0, mfn, mfn + NR_LT_CONFIG_PAGES - 1);
+
+        /*
+         * TBD: access to non-available device memory needs to return 0xff
+         * so we will need to map a page of 0xff's to all ranges except for
+         * TPM localities 0,1
+         */
+    }
+#endif
+
     BUG_ON(rc != 0);
 
     return 0;
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/e820.c
--- a/xen/arch/x86/e820.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/e820.c	Thu Sep 21 11:59:17 2006 +0800
@@ -31,7 +31,7 @@ static void __init add_memory_region(uns
     }
 } /* add_memory_region */
 
-static void __init print_e820_memory_map(struct e820entry *map, int entries)
+void __init print_e820_memory_map(struct e820entry *map, int entries)
 {
     int i;
 
@@ -51,6 +51,11 @@ static void __init print_e820_memory_map
         case E820_NVS:
             printk("(ACPI NVS)\n");
             break;
+#ifdef CONFIG_SMX
+        case E820_PROTECTED:
+            printk("(PROTECTED)\n");
+            break;
+#endif
         default:	printk("type %u\n", map[i].type);
             break;
         }
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c	Thu Sep 21 11:59:17 2006 +0800
@@ -777,7 +777,8 @@ int start_vmx(void)
 
     if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK )
     {
-        if ( (eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0 )
+        if ( (eax & (IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX |
+                     IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX) ) == 0x0)
         {
             printk("VMX disabled by Feature Control MSR.\n");
             return 0;
@@ -787,7 +788,7 @@ int start_vmx(void)
     {
         wrmsr(IA32_FEATURE_CONTROL_MSR,
               IA32_FEATURE_CONTROL_MSR_LOCK |
-              IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON, 0);
+              IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX, 0);
     }
 
     if ( !check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS,
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/mm.c	Thu Sep 21 11:59:17 2006 +0800
@@ -215,7 +215,12 @@ void arch_init_memory(void)
     /* Any areas not specified as RAM by the e820 map are considered I/O. */
     for ( i = 0, pfn = 0; i < e820.nr_map; i++ )
     {
+#ifdef CONFIG_SMX
+        if ( e820.map[i].type != E820_RAM &&
+             e820.map[i].type != E820_PROTECTED )
+#else
         if ( e820.map[i].type != E820_RAM )
+#endif
             continue;
         /* Every page from cursor to start of next RAM region is I/O. */
         rstart_pfn = PFN_UP(e820.map[i].addr);
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/setup.c	Thu Sep 21 11:59:17 2006 +0800
@@ -25,6 +25,9 @@
 #include <asm/desc.h>
 #include <asm/shadow.h>
 #include <asm/e820.h>
+#ifdef CONFIG_SMX
+#include <asm/smx/smx.h>
+#endif
 #include <acm/acm_hooks.h>
 
 extern void dmi_scan_machine(void);
@@ -328,6 +331,25 @@ void __init __start_xen(multiboot_info_t
                "(truncated length fields).\n");
 
     max_page = init_e820(e820_raw, &e820_raw_nr);
+
+#ifdef CONFIG_SMX
+    if ( smx_in_prot_env() ) {
+        /*
+         * set the LT memory regions to be reserved/protected regardless of
+         * what BIOS may have set them to, since we don't trust BIOS
+         */
+
+        /* we can't let execution continue if the LT memory regions */
+        /* haven't been protected */
+        /* TBD: we could just teardown the protected environment */
+        if ( smx_reserve_memory(&e820) == -1 ) {
+            printk("SMX: e820 map too small to protect LT memory regions\n");
+            EARLY_FAIL();
+        }
+        printk(KERN_INFO "Physical RAM map after LT regions added:\n");
+        print_e820_memory_map(e820.map, e820.nr_map);
+    }
+#endif
 
     modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
 
@@ -559,6 +581,20 @@ void __init __start_xen(multiboot_info_t
     if ( opt_watchdog ) 
         watchdog_enable();
 
+#ifdef CONFIG_SMX
+    if ( smx_in_prot_env() ) {
+        /*
+         * initialize the fixmap entries for LT pub/priv config regs
+         */
+        for ( i = 0; i < NR_LT_CONFIG_PAGES; i++ ) {
+            set_fixmap_nocache(FIX_LT_PUB_CONFIG_REGS_BASE + i,
+                               LT_PUB_CONFIG_REGS_BASE + i*PAGE_SIZE);
+            set_fixmap_nocache(FIX_LT_PRIV_CONFIG_REGS_BASE + i,
+                               LT_PRIV_CONFIG_REGS_BASE + i*PAGE_SIZE);
+        }
+    }
+#endif
+
     /* initialize access control security module */
     acm_init(&initrdidx, mbi, initial_images_start);
 
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/shutdown.c
--- a/xen/arch/x86/shutdown.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/shutdown.c	Thu Sep 21 11:59:17 2006 +0800
@@ -21,6 +21,9 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mpspec.h>
+#ifdef CONFIG_SMX
+#include <asm/smx/smx.h>
+#endif
 
 /* reboot_str: comma-separated list of reboot options. */
 static char __initdata reboot_str[10] = "";
@@ -49,6 +52,20 @@ void machine_halt(void)
     watchdog_disable();
     console_start_sync();
     smp_call_function(__machine_halt, NULL, 1, 0);
+
+#ifdef CONFIG_SMX
+    /* clear any sensitive info in BSP (if in protected env) */
+    smx_scrub_proc();
+
+    /* clear any sensitive info in memory (if in protected env) */
+    smx_scrub_mem();
+
+    hvm_disable();
+
+    /* teardown the protected environment (if any) */
+    smx_teardown(true);
+#endif
+
     __machine_halt(NULL);
 }
 
@@ -212,17 +229,42 @@ void machine_restart(char * __unused)
         /* Send IPI to the boot CPU (logical cpu 0). */
         on_selected_cpus(cpumask_of_cpu(0), (void *)machine_restart,
                          NULL, 1, 0);
+#ifndef CONFIG_SMX
+	printk("SMX: !!! should not be here\n");
+	/* we will rely on smp_send_stop() to shutdown VT/LT on APs */
         for ( ; ; )
             safe_halt();
+#endif
     }
 
     /*
      * Stop all CPUs and turn off local APICs and the IO-APIC, so
      * other OSs see a clean IRQ state.
      */
-    smp_send_stop();
+    smp_send_stop(true);
     disable_IO_APIC();
+
+#ifdef CONFIG_SMX
+    /* clear any sensitive info in BSP (if in protected env) */
+    smx_scrub_proc();
+
+    /* clear any sensitive info in memory (if in protected env) */
+    smx_scrub_mem();
+#endif
+
     hvm_disable();
+
+#ifdef CONFIG_SMX
+    /* teardown the protected environment (if any) */
+    smx_teardown(true);
+
+    /* TBD: eventually cap PCRs and allow restart without reboot, but until */
+    /* then prevent restart without platform reboot that clears PCRs */
+    /* regardless of whether we actually launched the protected environment */
+    reboot_thru_bios = 0;
+
+    machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+#endif
 
     /* Rebooting needs to touch the page at absolute address 0. */
     *((unsigned short *)__va(0x472)) = reboot_mode;
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smp.c
--- a/xen/arch/x86/smp.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/smp.c	Thu Sep 21 11:59:17 2006 +0800
@@ -21,6 +21,9 @@
 #include <asm/smpboot.h>
 #include <asm/hardirq.h>
 #include <asm/ipi.h>
+#ifdef CONFIG_SMX
+#include <asm/smx/smx.h>
+#endif
 #include <mach_apic.h>
 
 /*
@@ -307,14 +310,36 @@ static void stop_this_cpu (void *dummy)
     local_irq_disable();
     disable_local_APIC();
 
+    if ( dummy != NULL ) {
+        bool is_shutdown;
+
+	/* this routine (smp_send_stop()) is also used by gdb handler to */
+	/* temporarily stop APs; in that case we won't teardown VT */
+	is_shutdown = *(bool *)dummy;
+	if ( is_shutdown ) {
+#ifdef CONFIG_SMX
+	    /* clear any sensitive info in processor (if in protected env) */
+	    smx_scrub_proc();
+#endif
+	    hvm_disable();
+#ifdef CONFIG_SMX
+	    smx_teardown(false);
+#endif
+	}
+    }
+
     for ( ; ; )
         __asm__ __volatile__ ( "hlt" );
 }
 
-void smp_send_stop(void)
-{
+void smp_send_stop(bool is_shutdown)
+{
+    static bool s_is_shutdown;
+
+    s_is_shutdown = is_shutdown;
+
     /* Stop all other CPUs in the system. */
-    smp_call_function(stop_this_cpu, NULL, 1, 0);
+    smp_call_function(stop_this_cpu, &s_is_shutdown, 1, 0);
 
     local_irq_disable();
     disable_local_APIC();
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/arch/x86/smpboot.c	Thu Sep 21 11:59:17 2006 +0800
@@ -49,6 +49,9 @@
 #include <asm/div64.h>
 #include <asm/flushtlb.h>
 #include <asm/msr.h>
+#ifdef CONFIG_SMX
+#include <asm/smx/smx.h>
+#endif
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
 #include <smpboot_hooks.h>
@@ -920,10 +923,24 @@ static int __devinit do_boot_cpu(int api
 
 	smpboot_setup_warm_reset_vector(start_eip);
 
+#ifdef CONFIG_SMX
+	/*
+	 * once protected environment has been launched we cannot
+	 * use INIT-SIPI-SIPI to restart APs, which are in spin loop
+	 */
+	if ( smx_in_prot_env() ) {
+	    /* wakeup_secondary() would do this */
+	    atomic_set(&init_deasserted, 1);
+	    boot_error = smx_rlp_restart(cpu);
+	}
+	else
+	    boot_error = wakeup_secondary_cpu(apicid, start_eip);
+#else
 	/*
 	 * Starting actual IPI sequence...
 	 */
 	boot_error = wakeup_secondary_cpu(apicid, start_eip);
+#endif
 
 	if (!boot_error) {
 		/*
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/common/domctl.c
--- a/xen/common/domctl.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/common/domctl.c	Thu Sep 21 11:59:17 2006 +0800
@@ -19,6 +19,10 @@
 #include <xen/iocap.h>
 #include <xen/guest_access.h>
 #include <asm/current.h>
+#ifdef CONFIG_SMX
+#include <asm/smx/smx.h>
+#include <asm/smx/config_regs.h>
+#endif
 #include <public/domctl.h>
 #include <acm/acm_hooks.h>
 
@@ -619,12 +623,45 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
     case XEN_DOMCTL_iomem_permission:
     {
         struct domain *d;
+#ifdef CONFIG_SMX
+        unsigned long prot_mfn_s;
+        unsigned long prot_mfn_e;
+#endif
         unsigned long mfn = op->u.iomem_permission.first_mfn;
         unsigned long nr_mfns = op->u.iomem_permission.nr_mfns;
 
         ret = -EINVAL;
         if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */
             break;
+
+#ifdef CONFIG_SMX
+        if ( smx_in_prot_env() ) {
+            /*
+             * we need to prohibit mapping LT private config registers and
+             * all of LT device memory except TPM localities 0,1
+             */
+
+            /* private config regs */
+            prot_mfn_s = paddr_to_pfn(LT_PRIV_CONFIG_REGS_BASE);
+            prot_mfn_e = prot_mfn_s + NR_LT_CONFIG_PAGES;
+            if ( mfn >= prot_mfn_s && mfn < prot_mfn_e ) {
+                printk("SMX: DOM0_IOMEM_PERMISSION attempt to access LT "
+                       "region (mfn=%lx, nr_mfns=%lx)\n", mfn, nr_mfns);
+                break;
+            }
+            if ( mfn < prot_mfn_s && (mfn + nr_mfns) > prot_mfn_s ) {
+                printk("SMX: DOM0_IOMEM_PERMISSION attempt to access LT "
+                       "region (mfn=%lx, nr_mfns=%lx)\n", mfn, nr_mfns);
+                break;
+            }
+
+            /*
+             * TBD: access to non-available device memory needs to return 0xff
+             * so we will need to map a page of 0xff's to all ranges except for
+             * TPM localities 0,1
+             */
+        }
+#endif
 
         ret = -ESRCH;
         d = find_domain_by_id(op->domain);
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/common/gdbstub.c
--- a/xen/common/gdbstub.c	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/common/gdbstub.c	Thu Sep 21 11:59:17 2006 +0800
@@ -510,7 +510,7 @@ __trap_to_gdb(struct cpu_user_regs *regs
         gdb_ctx->connected = 1;
     }
 
-    smp_send_stop();
+    smp_send_stop(false);
 
     /* Try to make things a little more stable by disabling
        interrupts while we're here. */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/cpufeature.h
--- a/xen/include/asm-x86/cpufeature.h	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/include/asm-x86/cpufeature.h	Thu Sep 21 11:59:17 2006 +0800
@@ -76,6 +76,7 @@
 #define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
 #define X86_FEATURE_DSCPL	(4*32+ 4) /* CPL Qualified Debug Store */
 #define X86_FEATURE_VMXE	(4*32+ 5) /* Virtual Machine Extensions */
+#define X86_FEATURE_SMXE	(4*32+ 6) /* Safer Mode Extensions */
 #define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
 #define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
 #define X86_FEATURE_CID		(4*32+10) /* Context ID */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/e820.h
--- a/xen/include/asm-x86/e820.h	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/include/asm-x86/e820.h	Thu Sep 21 11:59:17 2006 +0800
@@ -11,6 +11,7 @@ struct e820map {
 };
 
 extern unsigned long init_e820(struct e820entry *, int *);
+extern void print_e820_memory_map(struct e820entry *, int);
 extern struct e820map e820;
 
 #endif /*__E820_HEADER*/
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/fixmap.h
--- a/xen/include/asm-x86/fixmap.h	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/include/asm-x86/fixmap.h	Thu Sep 21 11:59:17 2006 +0800
@@ -16,6 +16,10 @@
 #include <asm/apicdef.h>
 #include <asm/acpi.h>
 #include <asm/page.h>
+#ifdef CONFIG_SMX
+#include <asm/smx/smx.h>
+#include <asm/smx/config_regs.h>
+#endif
 
 /*
  * Here we define all the compile-time 'special' virtual
@@ -36,6 +40,11 @@ enum fixed_addresses {
     FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
     FIX_HPET_BASE,
     FIX_CYCLONE_TIMER,
+#ifdef CONFIG_SMX
+    FIX_LT_PRIV_CONFIG_REGS_BASE,
+    FIX_LT_PUB_CONFIG_REGS_BASE = FIX_LT_PRIV_CONFIG_REGS_BASE + NR_LT_CONFIG_PAGES,
+    FIX_LT_CONFIG_REGS_END = FIX_LT_PUB_CONFIG_REGS_BASE + NR_LT_CONFIG_PAGES,
+#endif
     __end_of_fixed_addresses
 };
 
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/msr.h
--- a/xen/include/asm-x86/msr.h	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/include/asm-x86/msr.h	Thu Sep 21 11:59:17 2006 +0800
@@ -116,9 +116,13 @@ static inline void wrmsrl(unsigned int m
 #define MSR_IA32_VMX_CR0_FIXED1                 0x487
 #define MSR_IA32_VMX_CR4_FIXED0                 0x488
 #define MSR_IA32_VMX_CR4_FIXED1                 0x489
-#define IA32_FEATURE_CONTROL_MSR                0x3a
-#define IA32_FEATURE_CONTROL_MSR_LOCK           0x1
-#define IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON   0x4
+
+#define IA32_FEATURE_CONTROL_MSR                       0x3a
+#define IA32_FEATURE_CONTROL_MSR_LOCK                  0x1
+#define IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX     0x2
+#define IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX    0x4
+#define IA32_FEATURE_CONTROL_MSR_SENTER_PARAM_CTL      0x7f00
+#define IA32_FEATURE_CONTROL_MSR_ENABLE_SENTER         0x8000
 
 /* AMD/K8 specific MSRs */ 
 #define MSR_EFER 0xc0000080		/* extended feature register */
@@ -145,8 +149,10 @@ static inline void wrmsrl(unsigned int m
 /* Intel MSRs. Some also available on other CPUs */
 #define MSR_IA32_PLATFORM_ID	0x17
 
-#define MSR_MTRRcap		0x0fe
-#define MSR_IA32_BBL_CR_CTL        0x119
+#define MSR_MTRRcap                     0x0fe
+#define MSR_IA32_MTRRCAP                MSR_MTRRcap
+#define MSR_IA32_MTRR_DEF_TYPE          0x2ff
+#define MSR_IA32_BBL_CR_CTL             0x119
 
 #define MSR_IA32_SYSENTER_CS		0x174
 #define MSR_IA32_SYSENTER_ESP		0x175
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/include/asm-x86/processor.h	Thu Sep 21 11:59:17 2006 +0800
@@ -80,6 +80,7 @@
 #define X86_CR4_OSFXSR		0x0200	/* enable fast FPU save and restore */
 #define X86_CR4_OSXMMEXCPT	0x0400	/* enable unmasked SSE exceptions */
 #define X86_CR4_VMXE		0x2000  /* enable VMX */
+#define X86_CR4_SMXE		0x4000	/* enable SMX */
 
 /*
  * Trap/fault mnemonics.
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/public/hvm/e820.h
--- a/xen/include/public/hvm/e820.h	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/include/public/hvm/e820.h	Thu Sep 21 11:59:17 2006 +0800
@@ -12,6 +12,11 @@
 #define E820_SHARED_PAGE 17
 #define E820_XENSTORE    18
 #define E820_BUFFERED_IO 19
+
+#ifdef CONFIG_SMX
+/* SMX extended E820 type */
+#define E820_PROTECTED   30      /* memory only available to hypervisor */
+#endif
 
 /* E820 location in HVM virtual address space. */
 #define E820_MAP_PAGE        0x00090000
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/xen/smp.h
--- a/xen/include/xen/smp.h	Tue Sep 19 14:26:47 2006 +0100
+++ b/xen/include/xen/smp.h	Thu Sep 21 11:59:17 2006 +0800
@@ -6,6 +6,7 @@
  *		Alan Cox. <alan@redhat.com>
  */
 
+#include <stdbool.h>
 #include <xen/config.h>
 
 #ifdef CONFIG_SMP
@@ -20,7 +21,7 @@
 /*
  * stops all CPUs but the current one:
  */
-extern void smp_send_stop(void);
+extern void smp_send_stop(bool is_shutdown);
 
 extern void smp_send_event_check_mask(cpumask_t mask);
 #define smp_send_event_check_cpu(cpu) \
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smx/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/smx/Makefile	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,6 @@
+obj-y += smx.o
+obj-y += mtrrs.o
+obj-y += acmod.o
+obj-y += tpm.o
+obj-y += errors.o
+obj-y += early_printk.o
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smx/acmod.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/smx/acmod.c	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,321 @@
+/*
+ * acmod.c: support functions for use of LT Authenticated Code (AC) Modules
+ *
+ * Copyright (c) 2003-2006, 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.
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/flushtlb.h>
+#include <asm/smx/smx.h>
+#include <asm/smx/acmod.h>
+#include <asm/smx/mtrrs.h>
+
+#define DEBUG_SMX 1
+
+#undef printk
+#ifdef DEBUG_SMX
+#define printk                 early_serial_printk
+#else
+#define printk(_f , _a...)
+#endif
+
+#define ACM_MEM_TYPE_UC                 0x0100
+#define ACM_MEM_TYPE_WC                 0x0200
+#define ACM_MEM_TYPE_WT                 0x1000
+#define ACM_MEM_TYPE_WP                 0x2000
+#define ACM_MEM_TYPE_WB                 0x4000
+
+/* this is arbitrary and can be increased when needed */
+#define MAX_SUPPORTED_ACM_VERSIONS      16
+
+typedef struct {
+    struct {
+        u32 mask;
+        u32 version;
+    } acm_versions[MAX_SUPPORTED_ACM_VERSIONS];
+    int n_versions;
+    u32 acm_max_size;
+    u32 acm_mem_types;
+    u32 senter_controls;
+} getsec_parameters_t;
+
+#define DEF_ACM_MAX_SIZE                0x8000
+#define DEF_ACM_VER_MASK                0xffffffff
+#define DEF_ACM_VER_SUPPORTED           0x00
+#define DEF_ACM_MEM_TYPES               ACM_MEM_TYPE_UC
+#define DEF_SENTER_CTRLS                0x00
+
+static int get_parameters(getsec_parameters_t *params)
+{
+    unsigned long cr4;
+    u32 index, eax, ebx, ecx;
+    int param_type;
+
+    /* sanity check because GETSEC[PARAMETERS] will fail if not set */
+    cr4 = read_cr4();
+    if ( !(cr4 & X86_CR4_SMXE) ) {
+        printk("SMX: SMXE not enabled, can't read parameters\n");
+        return -1;
+    }
+
+    memset(params, 0, sizeof(*params));
+    params->acm_max_size = DEF_ACM_MAX_SIZE;
+    params->acm_mem_types = DEF_ACM_MEM_TYPES;
+    params->senter_controls = DEF_SENTER_CTRLS;
+    index = 0;
+    do {
+        __getsec_parameters(index++, &param_type, &eax, &ebx, &ecx);
+        /* the code generated for a 'switch' statement doesn't work in this */
+        /* environment, so use if/else blocks instead */
+        if ( param_type == 0 )
+            ;
+        else if ( param_type == 1 ) {
+            if ( params->n_versions == MAX_SUPPORTED_ACM_VERSIONS )
+                printk("SMX: number of supported ACM version exceeds "
+                       "MAX_SUPPORTED_ACM_VERSIONS\n");
+            else {
+                params->acm_versions[params->n_versions].mask = ebx;
+                params->acm_versions[params->n_versions].version = ecx;
+                params->n_versions++;
+            }
+        }
+        else if ( param_type == 2 )
+            params->acm_max_size = eax & 0xffffffe0;
+        else if ( param_type == 3 )
+            params->acm_mem_types = eax & 0xffffffe0;
+        else if ( param_type == 4 )
+            params->senter_controls = (eax & 0x00007fff) >> 8;
+        else {
+            printk("SMX: unknown GETSEC[PARAMETERS] type: %d\n", param_type);
+            param_type = 0;    /* set so that we break out of the loop */
+        }
+    } while ( param_type != 0 );
+
+    if ( params->n_versions == 0 ) {
+        params->acm_versions[0].mask = DEF_ACM_VER_MASK;
+        params->acm_versions[0].version = DEF_ACM_VER_SUPPORTED;
+        params->n_versions = 1;
+    }
+
+    return 0;
+}
+
+void dump_acm_hdr(acm_hdr_t *hdr, const char *mod_name)
+{
+    printk("SMX: AC module header dump for %s:\n",
+           (mod_name == NULL) ? "?" : mod_name);
+    printk("SMX: \ttype %x\n", hdr->module_type);
+    printk("SMX: \tlength %x\n", hdr->header_len);
+    printk("SMX: \tversion %x\n", hdr->header_ver);
+    printk("SMX: \tid %x\n", hdr->module_id);
+    printk("SMX: \tvendor %x\n", hdr->module_vendor);
+    printk("SMX: \tdate %08x\n", hdr->date);
+    printk("SMX: \tsize %x\n", hdr->size);
+    printk("SMX: \tentry point %08x:%08x\n", hdr->seg_sel, hdr->entry_point);
+}
+
+int is_acmod(void *acmod_base)
+{
+    acm_hdr_t *acm_hdr;
+
+    acm_hdr = (acm_hdr_t *)acmod_base;
+
+    /* just check module_type */
+    if ( acm_hdr->module_type != ACM_VALID_MOD_TYPE ) {
+        dump_acm_hdr(acm_hdr, (const char *)__pa("INVALID MODULE"));
+        return 0;
+    }
+    else
+        return 1;
+}
+
+/*
+ * Do some AC module sanity checks because any violations will cause
+ * an LT.RESET.  Instead detect these, print a desriptive message,
+ * and skip SENTER/ENTERACCS
+ */
+int verify_acmod(void *acmod_base)
+{
+    acm_hdr_t *acm_hdr;
+    getsec_parameters_t params;
+    u32 size;
+
+    if ( !is_acmod(acmod_base) ) {
+        printk("SMX: not a valid AC module\n");
+        return -1;
+    }
+
+    acm_hdr = (acm_hdr_t *)acmod_base;
+    size = acm_hdr->size * 4;        /* hdr size is in dwords, we want bytes */
+
+    /*
+     * AC mod must start on 4k page boundary
+     */
+
+    if ( (unsigned long)acmod_base & 0xfff ) {
+        printk("SMX: AC mod base not 4K aligned (%p)\n", acmod_base);
+        return -1;
+    }
+    printk("SMX: AC mod base alignment OK\n");
+
+    /* AC mod size must:
+     * - be multiple of 64
+     * - greater than ???
+     * - less than max supported size for this processor
+     */
+
+    if ( (size == 0) ||
+         ((size % 64) != 0) ) { 
+        printk("SMX: AC mod size %x bogus\n", size);
+        return -1;
+    }
+
+    if ( get_parameters(&params) == -1 ) {
+        printk("SMX: get_parameters() failed\n");
+        return -1;
+    }
+
+    if ( size > params.acm_max_size ) {
+        printk("SMX: AC mod size too large: %x (max=%x)\n", size,
+               params.acm_max_size);
+        return -1;
+    }
+
+    printk("SMX: AC mod size OK\n");
+
+    /*
+     * perform checks on AC mod structure
+     */
+
+    /* print it for debugging */
+    dump_acm_hdr(acm_hdr, (const char *)__pa("SINIT"));
+
+    /* entry point is offset from base addr so make sure it is within module */
+    if ( acm_hdr->entry_point >= size ) {
+        printk("SMX: AC mod entry (%08x) >= AC mod size (%08x)\n",
+               acm_hdr->entry_point, size);
+        return -1;
+    }
+
+    if ( !acm_hdr->seg_sel           ||       /* invalid selector */
+         (acm_hdr->seg_sel & 0x07)   ||       /* LDT, PL!=0 */
+         (acm_hdr->seg_sel + 8 > acm_hdr->gdt_limit) ) {
+        printk("SMX: AC mod selector [%04x] bogus\n", acm_hdr->seg_sel);
+        return -1;
+    }
+
+    /* TBD: verify that AC mod matches with chipset */
+
+    return 0;
+}
+
+/*
+ * this must be done for each processor so that all have the same
+ * memory types
+ */
+int set_mtrrs_for_acmod(void *acmod_base, u32 acmod_size)
+{
+    unsigned long eflags;
+    unsigned long cr0, cr4;
+
+    /*
+     * need to do some things before we start changing MTRRs
+     *
+     * since this will modify some of the MTRRs, they should be saved first
+     * so that they can be restored once the AC mod is done
+     */
+
+    /* disable interrupts */
+    __save_flags(eflags);
+    __cli();
+
+    /* save CR0 then disable cache (CRO.CD=1, CR0.NW=0) */
+    cr0 = read_cr0();
+    write_cr0((cr0 & ~X86_CR0_NW) | X86_CR0_CD);
+
+    /* flush caches */
+    wbinvd();
+
+    /* save CR4 and disable global pages (CR4.PGE=0) */
+    cr4 = read_cr4();
+    write_cr4(cr4 & ~X86_CR4_PGE);
+
+    /* flush TLBs */
+    local_flush_tlb();
+
+    /* disable MTRRs */
+    set_all_mtrrs(false);
+
+    /*
+     * now set MTRRs for AC mod and rest of memory
+     */
+    set_mem_type(acmod_base, acmod_size, MTRR_TYPE_WRBACK);
+
+    /*
+     * now undo some of earlier changes and enable our new settings
+     */
+
+    /* flush caches */
+    wbinvd();
+
+    /* flush TLBs */
+    local_flush_tlb();
+    
+    /* enable MTRRs */
+    set_all_mtrrs(true);
+
+    /* restore CR0 (cacheing) */
+    write_cr0(cr0);
+
+    /* restore CR4 (global pages) */
+    write_cr4(cr4);
+
+    /* enable interrupts */
+    __restore_flags(eflags);
+
+    return 0;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smx/early_printk.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/smx/early_printk.c	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,254 @@
+/*
+ * early_printk.c: printk to serial for very early boot stages
+ *
+ * Copyright (c) 2006, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <asm/io.h>
+#include <xen/lib.h>
+#include <asm/processor.h>
+
+/*
+ * re-written parsing and formatting fns that don't rely on static data
+ */
+
+static int isdigit( int c )
+{
+    if ( c >= '0' && c <= '9' )
+        return 1;
+    else
+        return 0;
+}
+
+static char dec_digit( unsigned int i )
+{
+    return ('0' + i);
+}
+
+static char hex_digit( unsigned int i )
+{
+    if ( i < 10 )
+        return dec_digit( i );
+    return ('a' + (i-10));
+}
+
+static void fmt_val( char *str, size_t size, unsigned long long arg, int is_dec )
+{
+    char buf[128];
+    char *str2 = str;
+    char *s;
+
+    memset( buf, '\0', sizeof(buf) );
+
+    s = buf;
+    do {
+        if ( is_dec ) {
+            *s++ = dec_digit( (unsigned int)(arg % 10) );
+            arg = arg / 10;
+        }
+        else {
+            *s++ = hex_digit( (unsigned int)(arg & 0x0f) );
+            arg = arg >> 4;
+        }
+    } while ( arg != 0 );
+
+    /* buf is reversed string, so reverse copy */
+    s--;
+    while ( s >= buf && size > 0 ) {
+        *str2++ = *s--;
+        size--;
+    }
+}
+
+static void parse_fmt(char *str, size_t size, const char **pfmt, va_list *pap)
+{
+    const char *fmt = *pfmt;
+    int is_hex=0, is_dec=0, is_ptr=0, is_long=0, is_longlong=0, is_string=0;
+    int fill_size=0, fill_char=' ';
+    unsigned long long arg=0;
+    char buf[128];
+
+    fmt++;        /* skip '%' */
+
+    /* width specifiers */
+    if ( isdigit( *fmt ) ) {
+        if ( *fmt == '0' ) {
+            fill_char = '0';
+            fmt++;
+        }
+        fill_size = simple_strtol(fmt, NULL, 10);
+        while ( isdigit( *fmt ) )
+            fmt++;
+    }
+
+    /* parse format specifier */
+    if ( *fmt == 'L' ) {
+        is_longlong = 1;
+        fmt++;
+    }
+    else if ( *fmt == 'l' ) {
+        is_long = 1;
+        fmt++;
+    }
+    if ( *fmt == 'd' )
+        is_dec = 1;
+    else if ( *fmt == 's' )
+        is_string = 1;
+    else if ( *fmt == 'p' )
+        is_ptr = 1;
+    else                      /* 'x' */
+        is_hex = 1;
+    fmt++;
+
+    /* get param converted to type */
+    if ( is_longlong )
+        arg = (unsigned long long)va_arg( *pap, unsigned long long );
+    else if ( is_long )
+        arg = (unsigned long long)va_arg( *pap, unsigned long );
+    else if ( is_ptr )
+        arg = (unsigned long long)(unsigned long)va_arg( *pap, void* );
+    else if ( is_string )
+        arg = (unsigned long long)(unsigned long)va_arg( *pap, char* );
+    else
+        arg = (unsigned long long)va_arg( *pap, unsigned int );
+
+    /* handle neg # */
+    if ( is_dec && (signed long long)arg < 0 ) {
+        *str++ = '-';
+        size--;
+        arg = (unsigned long long)(-(signed long long)arg);
+    }
+    /* and %p */
+    else if ( is_ptr && size > 2 ) {
+        *str++ = '0'; *str++ = 'x';
+        size -= 2;
+    }
+
+    memset( buf, '\0', sizeof(buf) );
+    if ( is_string )
+        strncpy( buf, (const char *)(unsigned long)arg, sizeof(buf)-1);
+    else
+        fmt_val( buf, sizeof(buf), arg, is_dec );
+
+    if ( fill_size < strlen( buf ) )
+        fill_size = 0;
+    else
+        fill_size = fill_size - strlen( buf );
+
+    if ( strlen( buf ) + fill_size < size ) {
+        memset( str, fill_char, fill_size );
+        strcpy( str + fill_size, buf );
+    }
+
+    /* move pfmt foreward */
+    *pfmt = fmt;
+}
+
+static int early_vscnprintf(char *str, size_t size, const char *fmt,
+                            va_list ap)
+{
+    int n = 0;
+
+    while ( *fmt != '\0' && n < size-1 ) {
+        if ( *fmt == '%' ) {
+            char buf[256];
+            int sn;
+
+            memset( buf, '\0', sizeof(buf) );
+
+            parse_fmt( buf, sizeof(buf), &fmt, &ap );
+
+            sn = strlen( buf );
+            if ( sn > (size-n-1) )
+                sn = size - n - 1;
+            strncpy( str, buf, sn );
+            n += sn; str += sn;
+        }
+        else {
+            *str++ = *fmt++;
+            n++;
+        }
+    }
+    return n;
+}
+
+/*
+ * serial support from linux.../arch/x86_64/kernel/early_printk.c
+ *
+ * this code does not initialize the serial port and assumes COM1, so
+ * it will only display if GRUB has been configured for output to COM1
+ */
+
+#define early_serial_base    0x3f8      /* ttyS0 */
+
+#define XMTRDY          0x20
+
+#define DLAB		    0x80
+
+#define TXR             0       /*  Transmit register (WRITE) */
+#define RXR             0       /*  Receive register  (READ)  */
+#define IER             1       /*  Interrupt Enable          */
+#define IIR             2       /*  Interrupt ID              */
+#define FCR             2       /*  FIFO control              */
+#define LCR             3       /*  Line control              */
+#define MCR             4       /*  Modem control             */
+#define LSR             5       /*  Line Status               */
+#define MSR             6       /*  Modem Status              */
+#define DLL             0       /*  Divisor Latch Low         */
+#define DLH             1       /*  Divisor latch High        */
+
+static int early_serial_putc(unsigned char ch) 
+{ 
+    unsigned timeout = 0xffff; 
+    while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) 
+        cpu_relax();
+    outb(ch, early_serial_base + TXR);
+    return timeout ? 0 : -1;
+} 
+
+static void early_serial_write(const char *s, unsigned int n)
+{
+    while (*s && n-- > 0) { 
+        early_serial_putc(*s); 
+        if (*s == '\n') 
+            early_serial_putc('\r'); 
+        s++; 
+    } 
+}
+
+void early_serial_printk(const char *fmt, ...)
+{
+	char buf[512];
+	int n;
+	va_list ap;
+
+    memset(buf, '\0', sizeof(buf));
+	va_start(ap, fmt);
+    n = early_vscnprintf(buf, 512, (const char *)__pa(fmt), ap);
+	early_serial_write(buf, n);
+	va_end(ap);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smx/errors.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/smx/errors.c	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,108 @@
+/*
+ * errors.c: display LT error codes
+ *
+ * Copyright (c) 2003-2006, 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.
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <asm/smx/smx.h>
+#include <asm/smx/config_regs.h>
+
+
+#define DEBUG_SMX 1
+#undef printk
+#ifdef DEBUG_SMX
+#define printk                 early_serial_printk
+#else
+#define printk(_f , _a...)     /**/
+#endif
+
+/*
+ * format of LT.ERRORCODE's type field when its src field is 0
+ */
+typedef union {
+    u16 _raw;
+    struct {
+        u16 type      : 4;  /* 0000=BIOS ACM, 0001=SINIT, 0010-1111=reserved */
+        u16 progress  : 6;
+        u16 error     : 4;
+        u16 reserved  : 1;
+    };
+} acmod_error_t;
+
+void display_errors(void)
+{
+    lt_crash_t err;
+    lt_ests_t ests;
+    lt_e2sts_t e2sts;
+    acmod_error_t acmod_err;
+ 
+    /*
+     * display LT.CRASH error
+     */
+    err = (lt_crash_t)read_pub_config_reg(LTCR_LT_CRASH);
+    printk("SMX: LT.CRASH=%Lx\n", err._raw);
+
+    /* AC module error (don't know how to parse other errors) */
+    if ( err.valid && err.src == 0 ) {
+        acmod_err = (acmod_error_t)(u16)(err.type);
+        printk("SMX: AC module error : type=%x, progress=%02x, error=%x\n",
+               (u32)acmod_err.type, (u32)acmod_err.progress,
+               (u32)acmod_err.error);
+    }
+
+    /*
+     * display LT.ESTS error
+     */
+    ests = (lt_ests_t)read_pub_config_reg(LTCR_LT_ESTS);
+    printk("SMX: LT.ESTS=%Lx\n", ests._raw);
+
+    /*
+     * display LT.E2STS error
+     * - only valid if LT.WAKE-ERROR.STS set in LT.STS reg
+     */
+    if ( ests.lt_wake_error_sts ) {
+        e2sts = (lt_e2sts_t)read_pub_config_reg(LTCR_LT_E2STS);
+        printk("SMX: LT.E2STS=%Lx\n", e2sts._raw);
+    }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smx/mtrrs.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/smx/mtrrs.c	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,204 @@
+/*
+ * mtrrs.c: LT support functions for manipulating MTRRs
+ *
+ * Copyright (c) 2003-2006, 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.
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/msr.h>
+#include <asm/flushtlb.h>
+#include <asm/bitops.h>
+#include <asm/smx/smx.h>
+#include <asm/smx/mtrrs.h>
+
+#define DEBUG_SMX 1
+
+#undef printk
+#ifdef DEBUG_SMX
+#define printk                 early_serial_printk
+#else
+#define printk(_f , _a...)
+#endif
+
+void save_mtrrs(mtrr_state_t *saved_state)
+{
+    mtrr_cap_t mtrr_cap;
+    int ndx;
+
+    /* IA32_MTRR_DEF_TYPE MSR */
+    rdmsrl(MSR_IA32_MTRR_DEF_TYPE, saved_state->mtrr_def_type.raw);
+
+    /* number variable MTTRRs */
+    rdmsrl(MSR_IA32_MTRRCAP, mtrr_cap.raw);
+    if ( mtrr_cap.vcnt > MAX_VARIABLE_MTRRS ) {
+        /* print warning but continue saving what we can */
+        /* (set_mem_type() won't exceed the array, so we're safe doing this) */
+        printk("SMX: actual # var MTRRs (%d) > MAX_VARIABLE_MTRRS (%d)\n",
+               mtrr_cap.vcnt, MAX_VARIABLE_MTRRS);
+        saved_state->num_var_mtrrs = MAX_VARIABLE_MTRRS;
+    }
+    else
+        saved_state->num_var_mtrrs = mtrr_cap.vcnt;
+
+    /* physmask's and physbase's */
+    for ( ndx = 0; ndx < saved_state->num_var_mtrrs; ndx++ ) {
+        rdmsrl(MTRR_PHYS_MASK0_MSR + ndx*2,
+               saved_state->mtrr_physmasks[ndx].raw);
+        rdmsrl(MTRR_PHYS_BASE0_MSR + ndx*2,
+               saved_state->mtrr_physbases[ndx].raw);
+    }
+}
+
+void restore_mtrrs(mtrr_state_t *saved_state)
+{
+    int ndx;
+
+    /* TBD: we need to check these for validity (e.g. overlaping regions */
+    /* with invalid memory type combinations and variable MTRRs describing */
+    /* non-contiguous memory regions) */
+
+    /* IA32_MTRR_DEF_TYPE MSR */
+    wrmsrl(MSR_IA32_MTRR_DEF_TYPE, saved_state->mtrr_def_type.raw);
+
+    /* physmask's and physbase's */
+    for ( ndx = 0; ndx < saved_state->num_var_mtrrs; ndx++ ) {
+        wrmsrl(MTRR_PHYS_MASK0_MSR + ndx*2,
+               saved_state->mtrr_physmasks[ndx].raw);
+        wrmsrl(MTRR_PHYS_BASE0_MSR + ndx*2,
+               saved_state->mtrr_physbases[ndx].raw);
+    }
+}
+
+/*
+ * set the memory type for specified range (base to base+size)
+ * to mem_type and everything else to UC
+ */
+int set_mem_type(void *base, u32 size, u32 mem_type)
+{
+    int num_pages;
+    int ndx;
+    mtrr_def_type_t mtrr_def_type;
+    mtrr_cap_t mtrr_cap;
+    mtrr_physmask_t mtrr_physmask;
+    mtrr_physbase_t mtrr_physbase;
+
+    /*
+     * disable all fixed MTRRs
+     * set default type to UC
+     */
+    rdmsrl(MSR_IA32_MTRR_DEF_TYPE, mtrr_def_type.raw);
+    mtrr_def_type.fe = 0;
+    mtrr_def_type.type = MTRR_TYPE_UNCACHABLE;
+    wrmsrl(MSR_IA32_MTRR_DEF_TYPE, mtrr_def_type.raw);
+
+    /*
+     * initially disable all variable MTRRs (we'll enable the ones we use)
+     */
+    rdmsrl(MSR_IA32_MTRRCAP, mtrr_cap.raw);
+    for ( ndx = 0; ndx < mtrr_cap.vcnt; ndx++ ) {
+        rdmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw);
+        mtrr_physmask.v = 0;
+        wrmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw);
+    }
+
+    /*
+     * map all AC module pages as mem_type
+     */
+
+    num_pages = (size + PAGE_SIZE) >> PAGE_SHIFT;
+    ndx = 0;
+
+    printk("SMX: setting MTRRs for acmod: base=%p, size=%x, num_pages=%d\n",
+           base, size, num_pages);
+
+    while ( num_pages > 0 ) {
+        u32 pages_in_range;
+
+        /* set the base of the current MTRR */
+        rdmsrl(MTRR_PHYS_BASE0_MSR + ndx*2, mtrr_physbase.raw);
+        mtrr_physbase.base = (unsigned long)base >> PAGE_SHIFT;
+        mtrr_physbase.type = mem_type;
+        wrmsrl(MTRR_PHYS_BASE0_MSR + ndx*2, mtrr_physbase.raw);
+
+        /*
+         * calculate MTRR mask
+         * MTRRs can map pages in power of 2
+         * may need to use multiple MTRRS to map all of region
+         */
+        pages_in_range = 1 << (fls(num_pages) - 1);
+
+        rdmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw);
+        mtrr_physmask.mask = ~(pages_in_range - 1);
+        mtrr_physmask.v = 1;
+        wrmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw);
+
+        /* prepare for the next loop depending on number of pages
+         * We figure out from the above how many pages could be used in this 
+         * mtrr. Then we decrement the count, increment the base, 
+         * increment the mtrr we are dealing with, and if num_pages is 
+         * still not zero, we do it again.
+         */
+        base += (pages_in_range * PAGE_SIZE);
+        num_pages -= pages_in_range;
+        ndx++;
+        if ( ndx == mtrr_cap.vcnt ) {
+            printk("SMX: exceeded number of var MTRRs when mapping range\n");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/* enable/disable all MTRRs */
+void set_all_mtrrs(bool enable)
+{
+    mtrr_def_type_t mtrr_def_type;
+
+    rdmsrl(MSR_IA32_MTRR_DEF_TYPE, mtrr_def_type.raw);
+    mtrr_def_type.e = enable ? 1 : 0;
+    wrmsrl(MSR_IA32_MTRR_DEF_TYPE, mtrr_def_type.raw);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smx/smx.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/smx/smx.c	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,1062 @@
+/*
+ * smx.c: LT support functions and main entry points
+ *
+ * Copyright (c) 2003-2006, 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.
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/multiboot.h>
+#include <xen/smp.h>
+#include <asm/processor.h>
+#include <asm/fixmap.h>
+#include <asm/page.h>
+#include <asm/msr.h>
+#include <asm/ipi.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/delay.h>
+#include <asm/smx/smx.h>
+#include <asm/smx/config_regs.h>
+#include <asm/smx/acmod.h>
+
+
+#define DEBUG_SMX 1
+
+extern void * _text;        /* start of text section */
+extern void * __start;      /* Xen entry point in x86_{32,64}.S */
+extern void * _smx_wakeup;  /* RLP join address for GETSEC[WAKEUP] */
+
+/*
+ * flag to indicate when start_smx() is about to call SENTER
+ * used to determine if start_smx() is called first time or re-entry
+ * initialize to -1 so that it is not put in .bss (because .bss gets
+ * cleared each time before calling start_smx())
+ *
+ * use this instead of reading LT.STS.SENTER_DONE_STS config reg
+ * to allow for possiblity that we were called already in a protected
+ * environment; we need to know if our code launched it or not
+ */
+int _senter_start = -1;
+
+
+/*
+ * this is the structure whose addr we'll put in LT heap
+ */
+static mvmm_hdr_t _mvmm_hdr = {
+                    /* fixed values for ver 1.0 */
+    guid :          {0x9082ac5a, 0x74a7476f, 0xa2555c0f, 0x42b651cb},
+    length :        sizeof(mvmm_hdr_t),
+    version :       0x00010000,
+    entry_point :   0x00000000,     /* will be filled in later */
+    req_mem_size :  0,              /* Xen doesn't use this */
+    features :      0x00000000
+};
+
+
+/*
+ * we need to save these values in order to use when modifying the e820 map
+ * to reserve the LT regions because this gets done after paging has been
+ * enabled but before the fixmap has been initialized with the LT config
+ * registers regions, so the current code for reading the registers directly
+ * won't work at that time
+ */
+static struct lt_memory_regions_t {
+    u64 heap_base, heap_size;
+    u64 sinit_base, sinit_size;
+    u64 nodma_base, nodma_size;
+} _lt_memory_regions;
+
+
+/*
+ * misc. data that needs to be measured along with the hypervisor because
+ * it affects hypervisor security
+ * more items may be added over time
+ * we need to give it a default value to prevent it from being in bss
+ */
+#define MAX_XEN_CMD_LINE          1024
+static struct misc_measured_data_t {
+    char cmdline[MAX_XEN_CMD_LINE];
+} _misc_measured_data = {""};
+
+
+/*
+ * MVMM Join structure for bringing RLPs out of SENTER wait state
+ */
+static mvmm_join_t _mvmm_join;
+
+
+/*
+ * cpu # for processor/core/thread to bring out of post GETSEC[WAKEUP]
+ * spin loop as part of SMP startup routine
+ */
+int _smp_resume = -1;
+
+
+/*
+ * # cpu's (APs)
+ * during boot will increment to reflect total #
+ * during shutdown will decrement until all have shutdown
+ */
+static atomic_t _nr_cpus;
+
+
+unsigned long smx_rlp_restart(int cpu)
+{
+    printk("SMX: restarting cpu %d\n", cpu);
+
+    /* we are assuming that all cpus we want to start will start */
+    atomic_inc(&_nr_cpus);
+
+    _smp_resume = cpu;
+
+    return 0;
+}
+
+/* clear processor state of any secrets */
+void smx_scrub_proc(void)
+{
+    /* only scrub if we setup the environment */
+    if ( _senter_start != 1 )
+        return;
+
+    /* we don't have any secrets to clear, however */
+    ;
+}
+
+void smx_scrub_mem(void)
+{
+    /* only peform mem scrub if we setup the environment */
+    if ( _senter_start != 1 )
+        return;
+
+    /* scrub any secrets by clearing the memory */
+    /* we don't have any secrets to scrub, however */
+    ;
+
+    /* flush chipset caches and buffers */
+    write_priv_config_reg(LTCR_LT_CMD_FLUSH_WB, 0x01);
+    printk("SMX: memory scubbed\n");
+
+    /* TBD:  cap dynamic PCRs (17, 18) */
+
+    /* set LT.CMD.NO-SECRETS flag */
+    write_priv_config_reg(LTCR_LT_CMD_NO_SECRETS, 0x01);
+    read_priv_config_reg(LTCR_LT_E2STS);   /* just a fence, so ignore return */
+    printk("SMX: secrets flag cleared\n");
+
+    /* close LT private config space */
+    read_priv_config_reg(LTCR_LT_E2STS);   /* fence */
+    write_priv_config_reg(LTCR_LT_CMD_CLOSE_PRIVATE, 0x01);
+    read_pub_config_reg(LTCR_LT_E2STS);   /* fence */
+    printk("SMX: private config space closed\n");
+}
+
+void smx_teardown(bool is_bsp)
+{
+    int timeout = 10;
+
+    /* only peform teardown if we setup the environment */
+    if ( _senter_start != 1 )
+        return;
+
+    /* APs increment _nr_cpus_shutting_down so that BSP can wait on it */
+    if ( !is_bsp ) {
+        atomic_dec(&_nr_cpus);
+        return;
+    }
+
+    /* BSP needs to wait until all APs have gone through shutdown (disabled */
+    /* VMX, etc.) before calling GETSEC[SEXIT] else will hang */
+    /* but we won't wait forever */
+    while ( atomic_read(&_nr_cpus) != 0 && timeout > 0 ) {
+        /* if not all APs have shutdown, wait a little */
+        udelay(5);
+        timeout--;
+    }
+
+    /* don't call SEXIT if not all APs have shutdown, since it will just */
+    /* fault anyway, and this will hang system */
+    if ( timeout != 0 ) {
+        /* call GETSEC[SEXIT] */
+        __getsec_sexit();
+        printk("SMX: GETSEC[SEXIT] protected environment torn down\n");
+
+        /* since we've torn down the environment, clear _senter_start flag */
+        _senter_start = -1;
+    }
+    else
+        printk("SMX: timeout before all APs shutdown; not doing SEXIT\n");
+}
+
+static void dump_sinit_mdrs(lt_heap_data_hdr_t *lt_heap_data_hdr)
+{
+    sinit_mvmm_data_v1_t *sinit_mvmm_data;
+    sinit_mdr_t *mdr;
+    int i;
+    static char *mem_types[] = {"GOOD", "SMM OVERLAY", "SMM NON-OVERLAY",
+                                "PCIE CONFIG SPACE", "PROTECTED"};
+
+    if ( lt_heap_data_hdr->version != 0x01 ) {
+        printk("SMX: SINIT to MVMM data version incompatible (%x)\n",
+               lt_heap_data_hdr->version);
+        return;
+    }
+
+    sinit_mvmm_data = (sinit_mvmm_data_v1_t *)lt_heap_data_hdr;
+
+    for ( i = 0; i < sinit_mvmm_data->num_mdrs; i++ ) {
+        mdr = sinit_mvmm_data->mdrs + i;
+        printk("SMX: mdr[%d] :\n", i);
+        printk("SMX: \tstart = %08x:%08x\n", mdr->start_hi, mdr->start_lo);
+        printk("SMX: \tlength = %x%x\n", mdr->length_hi, mdr->length_lo);
+        if ( mdr->mem_type < sizeof(mem_types)/sizeof(mem_types[0]) )
+            printk("SMX: \tmem_type = %s\n", mem_types[mdr->mem_type]);
+        else
+            printk("SMX: \tmem_type = %d\n", (int)mdr->mem_type);
+    }
+}
+
+static int insert_after_region(struct e820map *e820, int pos,
+                               uint64_t addr, uint64_t size,
+                               uint32_t type)
+{
+    int i;
+
+    /* no more room */
+    if ( e820->nr_map + 1 >= E820MAX )
+        return -1;
+
+    /* shift (copy) everything up one entry */
+    for (i = e820->nr_map - 1; i > pos; i--)
+        e820->map[i+1] = e820->map[i];
+
+    /* now add our entry */
+    e820->map[pos+1].addr = addr;
+    e820->map[pos+1].size = size;
+    e820->map[pos+1].type = type;
+
+    e820->nr_map++;
+
+    return 0;
+}
+
+static void remove_region(struct e820map *e820, int pos)
+{
+    int i;
+
+    /* shift (copy) everything down one entry */
+    for (i = pos; i < e820->nr_map - 1; i++)
+        e820->map[i] = e820->map[i+1];
+
+    e820->nr_map--;
+}
+
+static int separate_region(struct e820map *e820, uint64_t new_addr,
+                           uint64_t new_size)
+{
+    int i;
+    uint64_t addr, size;
+    uint32_t type;
+
+    if ( new_size == 0 )
+        return 0;
+
+    /* find where our region belongs in the table and insert it */
+    for (i = 0; i < e820->nr_map; i++) {
+        addr = e820->map[i].addr;
+        size = e820->map[i].size;
+        type = e820->map[i].type;
+        /* is our region at the beginning of the current map region? */
+        if ( new_addr == addr ) {
+            if ( insert_after_region(e820, i-1, new_addr, new_size,
+                                     E820_PROTECTED) == -1 )
+                return -1;
+            break;
+        }
+        /* are we w/in the current map region? */
+        else if ( new_addr > addr && new_addr < (addr + size) ) {
+            if ( insert_after_region(e820, i, new_addr, new_size,
+                                     E820_PROTECTED) == -1 )
+                return -1;
+            /* fixup current region */
+            e820->map[i].size = new_addr - e820->map[i].addr;
+            i++;   /* adjust to always be that of our region */
+            /* insert a copy of current region (before adj) after us so */
+            /* that rest of code can be common with previous case */
+            if ( insert_after_region(e820, i, addr, size, type) == -1 )
+                return -1;
+            break;
+        }
+        /* is our region in a gap in the map? */
+        else if ( addr > new_addr ) {
+            if ( insert_after_region(e820, i-1, new_addr, new_size,
+                                     E820_PROTECTED) == -1 )
+                return -1;
+            break;
+        }
+    }
+    /* if we reached the end of the map without finding an overlapping */
+    /* region, insert us at the end (note that this test won't trigger */
+    /* for the second case above because the insert() will have incremented */
+    /* nr_map and so i++ will still be less) */
+    if ( i == e820->nr_map ) {
+        if ( insert_after_region(e820, i-1, new_addr, new_size,
+                                 E820_PROTECTED) == -1 )
+            return -1;
+        return 0;
+    }
+
+    i++;     /* move to entry after our inserted one (we're not at end yet) */
+
+    /* did we split the (formerly) previous region? */
+    if ( (new_addr >= e820->map[i].addr) &&
+         ((new_addr + new_size) < (e820->map[i].addr + e820->map[i].size)) ) {
+        /* then adjust the current region (adj size first) */
+        e820->map[i].size = (e820->map[i].addr + e820->map[i].size) -
+                            (new_addr + new_size);
+        e820->map[i].addr = new_addr + new_size;
+        return 0;
+    }
+
+    /* if our region completely covers any existing regions, delete them */
+    while ( (i < e820->nr_map) && ((new_addr + new_size) >=
+                                   (e820->map[i].addr + e820->map[i].size)) )
+        remove_region(e820, i);
+
+    /* finally, if our region partially overlaps an existing region, */
+    /* then truncate the exiting region */
+    if ( (i < e820->nr_map) && ((new_addr + new_size) > e820->map[i].addr) )
+        e820->map[i].addr = new_addr + new_size;
+
+    return 0;
+}
+
+int smx_reserve_memory(struct e820map *e820)
+{
+    struct lt_memory_regions_t *lt_mem_regions;
+    u64 base, size;
+    lt_heap_t *lt_heap;
+    lt_heap_data_hdr_t *lt_heap_data_hdr;
+
+    /*
+     * LT has three regions of RAM that need to be reserved for use by only the
+     * hypervisor; not even dom0 should have access:
+     *   LT heap, SINIT AC module, NoDMA table
+     */
+
+    lt_mem_regions = (struct lt_memory_regions_t *)&_lt_memory_regions;
+
+    /* LT heap */
+    base = lt_mem_regions->heap_base;
+    size = lt_mem_regions->heap_size;
+    printk("SMX: protecting LT heap (%Lx - %Lx) in e820 table\n", base,
+           (base + size - 1));
+    if ( separate_region(e820, base, size) == -1 )
+        return -1;
+
+    /* SINIT */
+    base = lt_mem_regions->sinit_base;
+    size = lt_mem_regions->sinit_size;
+    printk("SMX: protecting SINIT (%Lx - %Lx) in e820 table\n", base,
+           (base + size - 1));
+    if ( separate_region(e820, base, size) == -1 )
+        return -1;
+
+    /* NoDMA table */
+    base = lt_mem_regions->nodma_base;
+    size = lt_mem_regions->nodma_size;
+    printk("SMX: protecting NoDMA table (%Lx - %Lx) in e820 table\n", base,
+           (base + size - 1));
+    if ( separate_region(e820, base, size) == -1 )
+        return -1;
+
+    /* TBD: we will need to parse sinit_mvmm_data.mdrs records and ensure */
+    /* that we don't use inappropriate memory for domains */
+    /* (we can't use get_heap() because fixmap isn't setup yet) */
+    lt_heap = (lt_heap_t *)(unsigned long)lt_mem_regions->heap_base;
+    lt_heap_data_hdr = get_sinit_mvmm_data_start(lt_heap);
+    dump_sinit_mdrs(lt_heap_data_hdr);
+
+    return 0;
+}
+
+/* put after teardown fns because those use std printk() */
+#undef printk
+#ifdef DEBUG_SMX
+#define printk                 early_serial_printk
+#else
+#define printk(_f , _a...)     /**/
+#endif
+
+
+bool smx_in_prot_env(void)
+{
+    return (_senter_start != 1) ? false : true;
+}
+
+u32 config_reg_base_addr(u32 base_phys)
+{
+    unsigned long cr0;
+    int idx;
+
+    cr0 = read_cr0();
+
+    /* if paging has been enabled then must use fixmap */
+    if ( cr0 & X86_CR0_PG ) {
+        idx = (base_phys - LT_PUB_CONFIG_REGS_BASE) >> PAGE_SHIFT;
+        return fix_to_virt(FIX_LT_PUB_CONFIG_REGS_BASE + idx);
+    }
+    /* else can use physical addr directly */
+    else
+        return base_phys;
+}
+
+/*
+ * sets up LT heap
+ */
+static lt_heap_t *setup_lt_heap(void *ptab_base)
+{
+    lt_heap_t *lt_heap;
+    os_mvmm_data_v1_t *os_mvmm_data;
+    os_sinit_data_v1_t *os_sinit_data;
+
+    lt_heap = get_lt_heap();
+
+    /*
+     * BIOS to OS/loader data already setup by BIOS
+     */
+
+    /*
+     * OS/loader to MVMM data
+     */
+    os_mvmm_data = (os_mvmm_data_v1_t *)get_os_mvmm_data_start(lt_heap);
+    *get_data_size_addr(os_mvmm_data) = sizeof(*os_mvmm_data) + sizeof(u64);
+    memset(os_mvmm_data, 0, sizeof(*os_mvmm_data));
+    os_mvmm_data->version = 0x01;
+
+    /*
+     * OS/loader to SINIT data
+     */
+    os_sinit_data = (os_sinit_data_v1_t *)get_os_sinit_data_start(lt_heap);
+    *get_data_size_addr(os_sinit_data) = sizeof(*os_sinit_data) + sizeof(u64);
+    memset(os_sinit_data, 0, sizeof(*os_sinit_data));
+    os_sinit_data->version = 0x01;
+    /* this is phys addr */
+    os_sinit_data->mvmm_ptab_lo = (u32)ptab_base;
+    os_sinit_data->mvmm_ptab_hi = 0;
+    os_sinit_data->mvmm_size_lo = (u32)__pa(&_end) - (u32)__pa(&_text);
+    os_sinit_data->mvmm_size_hi = 0;
+    /* this is linear addr (offset from MVMM base) of mvmm header */
+    os_sinit_data->mvmm_hdr_base_lo = (u32)&_mvmm_hdr - (u32)&_text;
+    os_sinit_data->mvmm_hdr_base_hi = 0;
+
+    /*
+     * SINIT to MVMM data will be setup by SINIT
+     */
+
+    return lt_heap;
+}
+
+/* MVMM page table can only contain 4k pages */
+#define MVMM_PAGE_SHIFT          12
+#define MVMM_PAGE_SIZE           (1L << PAGE_SHIFT)
+#define MVMM_PAGE_MASK           (~(PAGE_SIZE-1))
+
+/* LT uses PAE format page table for MVMM page table */
+typedef u64    mvmm_pfn_t;
+
+#define MVMM_NUM_PTES            (MVMM_PAGE_SIZE / sizeof(mvmm_pfn_t))
+
+/* page dir/table entry is phys addr + P + R/W + PWT */
+#define MVMM_MAKE_PDTE(addr)     (((u64)(unsigned long)addr & MVMM_PAGE_MASK) \
+                                        | 0x01)
+
+/* page directory/table */
+typedef struct {
+    mvmm_pfn_t pdtes[MVMM_NUM_PTES];
+} mvmm_pg_dirtab_t;
+
+/* MVMM page table */
+typedef struct {
+    mvmm_pfn_t pg_dir_ptr[4];
+} mvmm_ptab_t;
+
+static void *build_mvmm_pagetable(multiboot_info_t *mbi)
+{
+    void *mvmm_addr, *mvmm_end;
+    void *next_ptab_pg;      /* page to use for next page dir or page table */
+    mvmm_ptab_t *ptab_base;
+    u32 ptab_size, mvmm_size;
+    mvmm_pfn_t *pde, *pte;
+    mvmm_pg_dirtab_t *pd, *pt;
+    struct misc_measured_data_t *misc_data;
+
+    /*
+     * requirements of MVMM page tables:
+     *   - must be in PAE format
+     *   - 4k pages
+     *   - breadth-first traversal must have increasing phys addrs
+     *   - all addrs must be: <640k or >1M, not overlap w/ device mem, <top mem
+     *   - page dirs must be in lower phys addr than page tables
+     *   - page dir ptr table must be in lower phys addr than page dirs
+     *
+     * phys addr of page dir and MVMM size stored in LT heap
+     * xen hypervisor already contig and in increasing phys addr order
+     */
+    /* TBD: need to add dom0 kernel, dom0 initrd, ACM policy */
+
+    mvmm_addr = (void *)__pa(&_text);
+    mvmm_end = (void *)__pa(&_end);
+    mvmm_size = mvmm_end - mvmm_addr;
+    printk("SMX: MVMM start=%p, end=%p, size=%x\n", mvmm_addr, mvmm_end,
+           mvmm_size);
+
+#define BAD_MVMM_MEM_LO         0x0a0000
+#define BAD_MVMM_MEM_HI         0x100000
+    /* MVMM can't be in [640k, 1M) (it's sufficient just to check mvmm_addr */
+    /* against 1M, since the hypervisor wouldn't fit below 640K anyway) */
+    if ( (unsigned long)mvmm_addr < BAD_MVMM_MEM_HI ) {
+        printf("SMX: MVMM spans [640k, 1M) region which is not permitted\n");
+        return NULL;
+    }
+    /* nor can it be >4GB */
+    if ( (unsigned long)mvmm_end > 0xffffffff ) {
+        printf("SMX: MVMM is above 4GB which is not permitted\n");
+        return NULL;
+    }
+
+    /* make copy of misc. data that needs to be measured */
+    misc_data = (struct misc_measured_data_t *)__pa(&_misc_measured_data);
+    memset(misc_data->cmdline, 0, MAX_XEN_CMD_LINE);
+    strncpy( misc_data->cmdline, (char *)mbi->cmdline, MAX_XEN_CMD_LINE-1);
+
+    /* calculate size needed for page table */
+    ptab_size = (mvmm_size >> MVMM_PAGE_SHIFT)  /* # pages = # pte's */
+                * sizeof(mvmm_pfn_t)            /* => size of pte's */
+                + MVMM_PAGE_SIZE                /* + 1 page dir */
+                + MVMM_PAGE_SIZE;               /* + page dir ptr table */
+    /* round up to nearest page */
+    ptab_size = (ptab_size + MVMM_PAGE_SIZE) & MVMM_PAGE_MASK;
+
+    /* place ptab_base below BAD_MVMM_MEM_LO */
+    ptab_base = (void *)((BAD_MVMM_MEM_LO - ptab_size) & MVMM_PAGE_MASK);
+
+    memset(ptab_base, 0, MVMM_PAGE_SIZE);
+    printk("SMX: ptab_size=%x, ptab_base=%p\n", ptab_size, ptab_base);
+
+    /* only 1 page dir */
+    pd = (void *)ptab_base + MVMM_PAGE_SIZE;
+    memset(pd, 0, MVMM_PAGE_SIZE);
+
+    /* only use first entry in page dir ptr table */
+    ptab_base->pg_dir_ptr[0] = MVMM_MAKE_PDTE(pd);
+    /* printk("SMX: pg_dir_ptr[0]=%Lx, pd=%p\n", ptab_base->pg_dir_ptr[0],
+              pd); */
+
+    next_ptab_pg = (void *)pd + MVMM_PAGE_SIZE;
+
+    /* outer loop is page dir (will break when reach end of MVMM) */
+    for ( pde = pd->pdtes; pde < (pd->pdtes + MVMM_PAGE_SIZE); pde++ ) {
+        pt = next_ptab_pg;
+        memset(pt, 0, MVMM_PAGE_SIZE);
+
+        next_ptab_pg += PAGE_SIZE;
+
+        *pde = MVMM_MAKE_PDTE(pt);
+        /* printk("SMX: *pde=%Lx, pt=%p\n", *pde, pt); */
+
+        /* inner loop is page table (will break when reach end of MVMM) */
+        for ( pte = pt->pdtes; pte < (pt->pdtes + MVMM_PAGE_SIZE); pte++ ) {
+            *pte = MVMM_MAKE_PDTE(mvmm_addr);
+            /* printk("SMX: *pte=%Lx, mvmm_addr=%p\n", *pte, mvmm_addr); */
+
+            mvmm_addr += PAGE_SIZE;
+
+            /* last page added to table, so exit all loops */
+            if ( mvmm_addr >= mvmm_end )
+                goto table_done;
+        }
+    }
+    printk("SMX: MVMM size exceeded page table size--not possible!\n");
+    return NULL;
+
+ table_done:
+    return ptab_base;
+}
+
+/*
+ * Verify that processor is LT-capable and enabled.
+ * Do some processor-related sanity checks here before calling SENTER
+ * because any violations will cause an LT.RESET.  Instead detect these,
+ * print a desriptive message, and skip LT protected launch.
+ */
+static int verify_processor_state(void)
+{
+    unsigned long eflags;
+    unsigned long cr0, cr4;
+    u32 eax, edx;
+    unsigned int cpu_capability[NCAPINTS];
+    capabilities_t cap;
+    lt_sts_t sts;
+    u64 mcg_cap, mcg_stat;
+    int i;
+
+    /*
+     * verify processor is capable of SMX
+     */
+    /* Xen only fills x86_capability word 0 */
+    cpu_capability[4] = cpuid_ecx(1);
+    if ( !(test_bit(X86_FEATURE_SMXE, cpu_capability)) ) {
+        printk("SMX: CPU does not support SMX\n");
+        return -1;
+    }
+
+    printk("SMX: processor is SMX-capable\n");
+
+    /* no need to verify VMX capability at this time */
+
+    /*
+     * ensure that SMX is enabled by feature control MSR
+     *
+     * enable VMX after SMX but disable VMX outside of SMX
+     * - this is most secure launch since it prevents full (transparent)
+     *   virtualzation if LT launch is disabled or fails
+     * - BIOS or bootloader should really have set and locked it
+     */
+
+    rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx);
+
+    if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK ) {
+        printk("SMX: IA32_FEATURE_CONTROL_MSR is locked (%x)\n", eax);
+        printk("SMX: \tIA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX=%d\n",
+               (eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX) ? 1 : 0);
+        printk("SMX: \tIA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX=%d\n",
+               (eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX) ? 1 : 0);
+        if ( (eax & IA32_FEATURE_CONTROL_MSR_ENABLE_SENTER) == 0x00 ) {
+            printk("SMX: SENTER disabled by feature control MSR\n");
+            return -1;
+        }
+    }
+    else {
+        printk("SMX: IA32_FEATURE_CONTROL_MSR_LOCK is not locked (%x)\n", eax);
+        /*
+         * for testing purposes we enable VMX outside of SMX as well so that
+         * if there was some error in the LT boot, VMX will continue to work
+         */
+        /* eax &= ~(u32)IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX; */
+        eax |= IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX |
+               IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX |
+               IA32_FEATURE_CONTROL_MSR_ENABLE_SENTER |
+               IA32_FEATURE_CONTROL_MSR_SENTER_PARAM_CTL |
+               IA32_FEATURE_CONTROL_MSR_LOCK;
+        wrmsr(IA32_FEATURE_CONTROL_MSR, eax, 0);
+        printk("SMX: IA32_FEATURE_CONTROL_MSR set to %x\n", eax);
+    }
+
+    /*
+     * check that not in VMX mode
+     */
+    cr4 = read_cr4();
+    printk("SMX: cr4=%lx\n", cr4);
+    if ( cr4 & X86_CR4_VMXE ) {
+        printk("SMX: already in VMX mode\n");
+        return -1;
+    }
+
+    /*
+     * enable SMX
+     */
+
+    write_cr4(cr4 | X86_CR4_SMXE);
+    /* set_in_cr4() would normally do this but it won't work properly
+     * until paging is enabled, so set this manually
+     * this is needed because cr4 will get re-set to it by x86_32.S
+     */
+    *((unsigned long*)__pa(&mmu_cr4_features)) |= X86_CR4_SMXE;
+
+    printk("SMX: SMX is enabled\n");
+
+    /*
+     * verify that an LT-capable chipset is present and 
+     * check that all needed SMX capabilities are supported
+     */
+
+    cap = __getsec_capabilities(0);
+    if ( !cap.chipset_present ) {
+	    printk("SMX: LT chipset not present\n");
+	    return -1;
+    }
+    if ( !(cap.senter && cap.sexit && cap.parameters && cap.smctrl
+           && cap.wakeup) ) {
+	    printk("SMX: insufficient SMX capabilities (%x)\n", cap._raw);
+	    return -1;
+    }
+
+    printk("SMX: LT chipset and all needed capabilities present\n");
+    
+    /*
+     * verify/set cr0 and EFLAGS pre-conditions for GETSEC[SENTER]
+     */
+
+    cr0 = read_cr0();
+    printk("SMX: cr0=%lx\n", cr0);
+
+    /* must be in protected mode (CR0.PE=1) */
+    if ( !(cr0 & X86_CR0_PE) ) {
+        printk("SMX: CR0.PE not set\n");
+        cr0 |= X86_CR0_PE;
+    }
+
+    /* cache must be enabled */
+    if ( cr0 & X86_CR0_CD ) {
+        printk("SMX: CR0.CD set\n");
+        cr0 &= ~X86_CR0_CD;
+    }
+    if ( cr0 & X86_CR0_NW ) {
+        printk("SMX: CR0.NW set\n");
+        cr0 &= ~X86_CR0_NW;
+    }
+
+    /* native FPU error reporting must be enabled for proper */
+    /* interaction behavior */
+    if ( !(cr0 & X86_CR0_NE) ) {
+        printk("SMX: CR0.NE not set\n");
+        cr0 |= X86_CR0_NE;
+    }
+
+    write_cr0(cr0);
+
+    /* cannot be in virtual-8086 mode (EFLAGS.VM=1) */
+    __save_flags(eflags);
+    if ( eflags & X86_EFLAGS_VM ) {
+        printk("SMX: EFLAGS.VM set\n");
+        __restore_flags(eflags | X86_EFLAGS_VM);
+    }
+
+    printk("SMX: CR0 and EFLAGS OK\n");
+
+    /*
+     * verify that we're not already in a protected environment
+     */
+    sts = (lt_sts_t)read_pub_config_reg(LTCR_LT_STS);
+    if ( sts.senter_done_sts ) {
+        printk("SMX: already in protected environment\n");
+        return -1;
+    }
+
+    /*
+     * verify all machine check status registers are clear
+     */
+
+    /* no machine check in progress (IA32_MCG_STATUS.MCIP=1)*/
+    rdmsrl(MSR_IA32_MCG_STATUS, mcg_stat);
+    if ( mcg_stat & 0x04 ) {
+        printk("SMX: machine check in progress\n");
+        return -1;
+    }
+
+    /* all machine check regs are clear */
+    rdmsrl(MSR_IA32_MCG_CAP, mcg_cap);
+    for (i = 0; i < (mcg_cap & 0xff); i++) {
+        rdmsrl(MSR_IA32_MC0_STATUS + 4*i, mcg_stat);
+        if ( mcg_stat & (1ULL << 63) ) {
+            printk("SMX: MCG[%d] = %Lx ERROR\n", i, mcg_stat);
+            return -1;
+        }
+    }
+
+    printk("SMX: no machine check errors\n");
+
+    /* all is well with the processor state */
+    printk("SMX: verify_processor_state() passed\n");
+
+    return 0;
+}
+
+/*
+ * Restore previous MTRRs and do other cleanup stuff here
+ *
+ * @return multiboot_info_t structure for use by Xen
+ */
+multiboot_info_t* restore_os_state(void)
+{
+    multiboot_info_t *mbi;
+    lt_heap_t *lt_heap;
+    os_mvmm_data_v1_t *os_mvmm_data;
+    struct lt_memory_regions_t *lt_mem_regions;
+
+    printk("SMX: restoring OS state\n");
+
+    /* clear error config registers so that we start fresh */
+    write_priv_config_reg(LTCR_LT_CRASH, 0x00000000);
+    write_priv_config_reg(LTCR_LT_ESTS, 0xffffffff);  /* write 1's to clear */
+
+    /* save the LT memory regions info for use in fixing-up e820 map */
+    lt_mem_regions = (struct lt_memory_regions_t *)__pa(&_lt_memory_regions);
+    lt_mem_regions->heap_base = read_pub_config_reg(LTCR_LT_HEAP_BASE);
+    lt_mem_regions->heap_size = read_pub_config_reg(LTCR_LT_HEAP_SIZE);
+    lt_mem_regions->sinit_base = read_pub_config_reg(LTCR_LT_SINIT_BASE);
+    lt_mem_regions->sinit_size = read_pub_config_reg(LTCR_LT_SINIT_SIZE);
+    lt_mem_regions->nodma_base = read_pub_config_reg(LTCR_LT_NODMA_BASE);
+    /* size encoding is 0=128k, 1=256k, 2=512k, ... = 128k*2^val, so convert */
+    lt_mem_regions->nodma_size = read_pub_config_reg(LTCR_LT_NODMA_SIZE);
+    lt_mem_regions->nodma_size = 0x20000ULL << lt_mem_regions->nodma_size;
+
+    /* get saved OS state (os_mvmm_data_t) from LT heap */
+    lt_heap = get_lt_heap();
+    os_mvmm_data = (os_mvmm_data_v1_t *)get_os_mvmm_data_start(lt_heap);
+
+    /* restore pre-SENTER MTRRs that were overwritten for SINIT launch */
+    restore_mtrrs(&(os_mvmm_data->saved_mtrr_state));
+
+    /* enable SMIs */
+    __getsec_smctrl();
+
+    /* always set the LT.CMD.SECRETS flag */
+    /* TBD: we really don't have any secrets yet, so we could skip this */
+    /* or we could provide an API to allow domains to set it if they have */
+    /* secrets */
+    write_priv_config_reg(LTCR_LT_CMD_SECRETS, 0x01);
+    read_priv_config_reg(LTCR_LT_E2STS);   /* just a fence, so ignore return */
+    printk("SMX: set LT.CMD.SECRETS flag\n");
+
+    /* restore mbi */
+    mbi = os_mvmm_data->mbi;
+
+    /* copy back the command line that we saved and measured */
+    strcpy((char *)mbi->cmdline, ((struct misc_measured_data_t *)
+                                  __pa(&_misc_measured_data))->cmdline);
+
+    /* decrement module count so that SINIT is not counted as Dom0's initrd */
+    mbi->mods_count--;
+
+    /* __start is expecting mbi to be virt addr, so convert it */
+    mbi = (multiboot_info_t *)__va(mbi);
+
+    /* push mbi onto the stack so that it can be restored to ebx */
+    return mbi;
+}
+
+static void *copy_sinit(void *src_base, u32 src_size)
+{
+    void *dest_base;
+    u32 dest_size;
+    acm_hdr_t *acm_hdr;
+    lt_heap_t *lt_heap;
+    lt_heap_data_hdr_t *lt_heap_data_hdr;
+    bios_os_data_v0_t *bios_os_data;
+
+    /* get BIOS-reserved region from LT.SINIT.BASE config reg */
+    dest_base = (void *)(unsigned long)read_pub_config_reg(LTCR_LT_SINIT_BASE);
+    dest_size = (u32)read_pub_config_reg(LTCR_LT_SINIT_SIZE);
+
+    /* make sure it fits */
+    if ( dest_size < src_size ) {
+        printk("SMX: BIOS-reserved SINIT size (%x) is too small for loaded "
+               "SINIT (%x)\n", dest_size, src_size);
+        return NULL;
+    }
+
+    /* check size of loaded module against internal size */
+    acm_hdr = (acm_hdr_t *)src_base;
+    if ( (acm_hdr->size * 4) != src_size ) {
+        printk("SMX: loaded SINIT size (%x) not same as internal size (%x)\n",
+               src_size, acm_hdr->size);
+        return NULL;
+    }
+
+    /* check if BIOS already loaded an SINIT module there */
+    /* (but replace it even if it has been loaded) */
+    lt_heap = get_lt_heap();
+    lt_heap_data_hdr = get_bios_os_data_start(lt_heap);
+    if ( lt_heap_data_hdr->version != 0x00 ) {
+        printk("SMX: BIOS to OS data version incompatible (%x)\n",
+               lt_heap_data_hdr->version);
+        return NULL;
+    }
+    bios_os_data = (bios_os_data_v0_t *)lt_heap_data_hdr;
+    if ( bios_os_data->bios_sinit_size != 0 ) {
+        printk("SMX: BIOS has already loaded an SINIT module\n");
+        dump_acm_hdr(dest_base, (const char *)__pa("BIOS SINIT"));
+        /* assume our SINIT is newer and replace BIOS's */
+    }
+
+    memcpy(dest_base, src_base, src_size);
+
+    printk("SMX: copied SINIT (size=%x) to %p\n", src_size, dest_base);
+
+    return dest_base;
+}
+
+static void smx_wakeup_cpus(void)
+{
+    struct Xgt_desc_struct gdt;
+    u16 cs;
+    mvmm_join_t *mvmm_join;
+
+    /* RLPs will use our GDT and CS */
+    __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&gdt) : "memory");
+    __asm__ __volatile__ ("movl %%cs, %0\n" : "=r"(cs));
+      
+    mvmm_join = (mvmm_join_t *)__pa(&_mvmm_join);
+    mvmm_join->entry_point = __pa(&_smx_wakeup);
+    mvmm_join->seg_sel = cs;
+    mvmm_join->gdt_base = __pa(gdt.address);
+    mvmm_join->gdt_limit = gdt.size;
+ 
+    printk("SMX: _mvmm_join.entry_point = %x\n", mvmm_join->entry_point);
+    printk("SMX: _mvmm_join.seg_sel = %x\n", mvmm_join->seg_sel);
+    printk("SMX: _mvmm_join.gdt_base = %x\n", mvmm_join->gdt_base);
+    printk("SMX: _mvmm_join.gdt_limit = %x\n", mvmm_join->gdt_limit);
+ 
+    write_priv_config_reg(LTCR_LT_MVMM_JOIN, __pa(&_mvmm_join));
+      
+    printk("SMX: joining RLPs to MVMM with GETSEC[WAKEUP]\n");
+    __getsec_wakeup();
+     
+    printk("SMX: GETSEC[WAKEUP] completed\n");
+}
+
+multiboot_info_t* start_smx(multiboot_info_t *mbi)
+{
+    module_t *sinit_mod;
+    void *sinit_base;
+    u32 sinit_size;
+    lt_heap_t *lt_heap;
+    os_mvmm_data_v1_t *os_mvmm_data;
+    void *mvmm_ptab_base;
+    mvmm_hdr_t *mvmm_hdr;
+    multiboot_info_t *virt_mbi;
+    atomic_t *nr_cpus;
+
+    /*
+     * check if this is being called as part of the SENTER re-start and
+     * if so, wakeup RLPs then call restore_os_state()
+     */
+    if ( *((int *)__pa(&_senter_start)) == 1 ) {
+        smx_wakeup_cpus();
+        return restore_os_state();
+    }
+
+    /* clear SENTER flag */
+    *((int *)__pa(&_senter_start)) = -1;
+
+    /* clear # cpus */
+    nr_cpus = (atomic_t *)__pa(&_nr_cpus);
+    atomic_set(nr_cpus, 0);
+
+    printk("SMX: start_smx()\n");
+
+    /* check if there was an error on last boot and print it */
+    display_errors();
+
+    /* the mbi we get is adjusted to be at virt addr, so covert back to phys */
+    virt_mbi = mbi;
+    mbi = (multiboot_info_t *)__pa(mbi);
+
+    /* check that we have at least one multiboot module - SINIT */
+    if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) ) {
+        printk("SMX: no SINIT module provided\n");
+        return virt_mbi;
+    }
+
+    /* verify the processor is LT capable and enabled */
+    if ( verify_processor_state() == -1 )
+        return virt_mbi;
+
+    /*
+     * copy SINIT to memory reserved for it by BIOS
+     */
+    /* expect SINIT to be last of GRUB modules */
+    sinit_mod = (module_t *)(mbi->mods_addr);
+    sinit_base = (void *)sinit_mod[mbi->mods_count-1].mod_start;
+    sinit_size = sinit_mod[mbi->mods_count-1].mod_end -
+                 (unsigned long)sinit_base;
+    /* check if this is really an SINIT AC module */
+    if ( !is_acmod(sinit_base) ) {
+        printk("SMX: could not find SINIT AC module\n");
+        return virt_mbi;
+    }
+    /* copy it */
+    sinit_base = copy_sinit(sinit_base, sinit_size);
+    if ( sinit_base == NULL )
+        return virt_mbi;
+
+    /* verify things are nominally OK */
+    if ( (verify_acmod(sinit_base) == -1) ||
+         (verify_tpm_ready() == -1) )
+             return virt_mbi;
+
+    /* set the MVMM entry point in the MVMM header */
+    /* entry point is relative to beginning of MVMM */
+    mvmm_hdr = (mvmm_hdr_t *)__pa(&_mvmm_hdr);
+    mvmm_hdr->entry_point = (u32)__pa(&__start) - (u32)__pa(&_text);
+    printk("SMX: MVMM entry point = %x\n", mvmm_hdr->entry_point);
+
+    /* create MVMM page table */
+    mvmm_ptab_base = build_mvmm_pagetable(mbi);
+    if ( mvmm_ptab_base == NULL )
+        return virt_mbi;
+
+    /* setup LT heap */
+    lt_heap = setup_lt_heap(mvmm_ptab_base);
+    os_mvmm_data = (os_mvmm_data_v1_t *)get_os_mvmm_data_start(lt_heap);
+
+    /* save mbi */
+    os_mvmm_data->mbi = mbi;
+
+    /* save MTRRs before we alter them for SINIT launch */
+    save_mtrrs(&(os_mvmm_data->saved_mtrr_state));
+
+    /* set MTRRs properly for AC module (SINIT) */
+    set_mtrrs_for_acmod(sinit_base, sinit_size);
+
+    /* set flag that we're about to do SENTER */
+    *((int *)__pa(&_senter_start)) = 1;
+
+    printk("SMX: executing GETSEC[SENTER]...\n");
+    __getsec_senter((u32)sinit_base, sinit_size);
+    printk("SMX: ERROR--we should not get here!\n");
+    return virt_mbi;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/arch/x86/smx/tpm.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/smx/tpm.c	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,164 @@
+/*
+ * tpm.c: TPM-related support functions for LT
+ *
+ * Copyright (c) 2003-2006, 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.
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/smx/smx.h>
+
+
+#define DEBUG_SMX 1
+
+#undef printk
+#ifdef DEBUG_SMX
+#define printk                 early_serial_printk
+#else
+#define printk(_f , _a...)     /**/
+#endif
+
+/*
+ * TPM registers and data structures
+ *
+ * register values are offsets from each locality base
+ * see {read,write}_tpm_reg() for data struct format
+ */
+
+/* TPM_ACCESS_x */
+#define TPM_REG_ACCESS           0x00
+typedef union {
+    u8 _raw[1];                      /* 1-byte reg */
+    struct {
+        u8 tpm_establishment   : 1;  /* RO, 0=T/OS has been established
+                                        before */
+        u8 request_use         : 1;  /* RW, 1=locality is requesting TPM use */
+        u8 pending_request     : 1;  /* RO, 1=other locality is requesting
+                                        TPM usage */
+        u8 seize               : 1;  /* WO, 1=seize locality */
+        u8 been_seized         : 1;  /* RW, 1=locality seized while active */
+        u8 active_locality     : 1;  /* RW, 1=locality is active */
+        u8 reserved            : 1;
+        u8 tpm_reg_valid_sts   : 1;  /* RO, 1=other bits are valid */
+    } __attribute__ ((packed));
+} tpm_reg_access_t;
+
+/* TPM_STS_x */
+#define TPM_REG_STS              0x18
+typedef union {
+    u8 _raw[3];                  /* 3-byte reg */
+    struct {
+        u8 reserved1       : 1;
+        u8 response_retry  : 1;  /* WO, 1=re-send response */
+        u8 reserved2       : 1;
+        u8 expect          : 1;  /* RO, 1=more data for command expected */
+        u8 data_avail      : 1;  /* RO, 0=no more data for response */
+        u8 tpm_go          : 1;  /* WO, 1=execute sent command */
+        u8 command_ready   : 1;  /* RW, 1=TPM ready to receive new cmd */
+        u8 sts_valid       : 1;  /* RO, 1=data_avail and expect bits are
+                                    valid */
+        u16 burst_count    : 16; /* RO, # read/writes bytes before wait */
+    } __attribute__ ((packed));
+} tpm_reg_sts_t;
+
+/*
+ * assumes that all reg types follow above format:
+ *   - packed
+ *   - member named '_raw' which is array whose size is that of data to read
+ */
+#define read_tpm_reg(locality, reg, pdata)      \
+    _read_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata)))
+
+#define write_tpm_reg(locality, reg, pdata)     \
+    _write_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata)))
+
+
+static void _read_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size)
+{
+    size_t i;
+    for ( i = 0; i < size; i++ )
+        _raw[i] = readb((TPM_LOCALITY_BASE_N(locality) | reg) + i);
+}
+
+static void _write_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size)
+{
+    size_t i;
+    for ( i = 0; i < size; i++ )
+        writeb(_raw[i], (TPM_LOCALITY_BASE_N(locality) | reg) + i);
+}
+
+
+/* ensure TPM is ready to accept commands */
+int verify_tpm_ready()
+{
+    tpm_reg_access_t reg_acc;
+    tpm_reg_sts_t reg_sts;
+
+    /*
+     * must ensure TPM_ACCESS_0.activeLocality bit is clear
+     * (: locality is not active)
+     */
+    read_tpm_reg(0, TPM_REG_ACCESS, &reg_acc);
+    if ( reg_acc.active_locality != 0 ) {
+        /* make inactive by writing a 1 */
+        reg_acc.active_locality = 1;
+        write_tpm_reg(0, TPM_REG_ACCESS, &reg_acc);
+    }
+
+    /*
+     * read TPM status register to check if it is ready to accept a command
+     * we can do this for locality 2 and assume same for other localities
+     * we will not wait on it--if it is not ready then error
+     */
+    read_tpm_reg(2, TPM_REG_STS, &reg_sts);
+    if ( !reg_sts.command_ready ) {
+        printk("SMX: TPM is not ready for commands\n");
+        return -1;
+    }
+
+    printk("SMX: TPM is ready\n");
+
+    return 0;
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/smx/acmod.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/smx/acmod.h	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,88 @@
+/*
+ * acmod.h: LT Authenticated Code (AC) Modules -related definitions
+ *
+ * Copyright (c) 2003-2006, 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 __ASM_X86_SMX_ACMOD_H__
+#define __ASM_X86_SMX_ACMOD_H__
+
+#include <asm/types.h>
+
+/*
+ * authenticated code (AC) module header (ver 0.0)
+ */
+
+typedef struct {
+    u32 module_type;
+    u32 header_len;
+    u32 header_ver;
+    u32 module_id;
+    u32 module_vendor;
+    u32 date;
+    u32 size;
+    u32 reserved1;
+    u32 code_control;
+    u32 error_entry_point;
+    u32 gdt_limit;
+    u32 gdt_base;
+    u32 seg_sel;
+    u32 entry_point;
+    u8  reserved2[64];
+    u32 key_size;
+    u32 scratch_size;
+    u8  rsa2048_pubkey[256];
+    u32 pub_exp;
+    u8  rsa2048_sig[256];
+    u32 scratch[143];
+    u8  user_area[];
+} acm_hdr_t;
+
+/* value of mod_type field for valid AC module */
+#define ACM_VALID_MOD_TYPE        0x02
+
+extern void dump_acm_hdr(acm_hdr_t *hdr, const char *mod_name);
+extern int verify_acmod(void *acmod_base);
+extern int set_mtrrs_for_acmod(void *acmod_base, u32 acmod_size);
+extern int is_acmod(void *acmod_base);
+
+#endif /* __ASM_X86_SMX_ACMOD_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/smx/config_regs.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/smx/config_regs.h	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,189 @@
+/*
+ * mtrrs.c: LT configuration register -related definitions
+ *
+ * Copyright (c) 2003-2006, 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 __ASM_X86_SMX_CONFIG_REGS_H__
+#define __ASM_X86_SMX_CONFIG_REGS_H__
+
+/*
+ * LT configuration registers (offsets from LT_{PUB, PRIV}_CONFIG_REGS_BASE)
+ */
+
+#define LT_PUB_CONFIG_REGS_BASE       0xfed30000
+#define LT_PRIV_CONFIG_REGS_BASE      0xfed20000
+
+/* # pages for each config regs space - used by fixmap */
+#define NR_LT_CONFIG_PAGES            ((LT_PUB_CONFIG_REGS_BASE - \
+                                        LT_PRIV_CONFIG_REGS_BASE) >>    \
+                                       PAGE_SHIFT)
+
+#define LTCR_LT_STS                   0x0000
+#define LTCR_LT_ESTS                  0x0008
+#define LTCR_LT_CRASH                 0x0030
+#define LTCR_LT_CMD_SYS_RESET         0x0038
+#define LTCR_LT_CMD_OPEN_PRIVATE      0x0040
+#define LTCR_LT_CMD_CLOSE_PRIVATE     0x0048
+#define LTCR_LT_CMD_FLUSH_WB          0x0258
+#define LTCR_LT_NODMA_BASE            0x0260
+#define LTCR_LT_NODMA_SIZE            0x0268
+#define LTCR_LT_SINIT_BASE            0x0270
+#define LTCR_LT_SINIT_SIZE            0x0278
+#define LTCR_LT_MVMM_JOIN             0x0290
+#define LTCR_LT_HEAP_BASE             0x0300
+#define LTCR_LT_HEAP_SIZE             0x0308
+#define LTCR_LT_CMD_SECRETS           0x08e0
+#define LTCR_LT_CMD_NO_SECRETS        0x08e8
+#define LTCR_LT_E2STS                 0x08f0
+
+/*
+ * format of LT.CRASH register
+ */
+typedef union {
+    u64 _raw;
+    struct {
+        u64 type       : 15;    /* src-specific error code */
+        u64 src        : 1;     /* 0=AC module */
+        u64 reserved   : 14;
+        u64 external   : 1;     /* 0=from proc, 1=from external SW */
+        u64 valid      : 1;     /* 1=valid */
+    };
+} lt_crash_t;
+
+/*
+ * format of LT.ESTS register
+ */
+typedef union {
+    u64 _raw;
+    struct {
+        u64 reserved1         : 1;
+        u64 lt_rogue_sts      : 1;
+        u64 bm_write_attack   : 1;
+        u64 bm_read_attack    : 1;
+        u64 fsb_write_attack  : 1;
+        u64 fsb_read_attack   : 1;
+        u64 lt_wake_error_sts : 1;
+        u64 reserved2         : 1;
+    };
+} lt_ests_t;
+
+/*
+ * format of LT.E2STS register
+ */
+typedef union {
+    u64 _raw;
+    struct {
+        u64 lt_slp_entry_error_sts  : 1;
+        u64 lt_secrets_sts          : 1;
+        u64 lt_block_mem_sts        : 1;
+        u64 lt_reset_sts            : 1;
+    };
+} lt_e2sts_t;
+
+/*
+ * format of LT.STS register
+ */
+typedef union {
+    u64 _raw;
+    struct {
+        u64 senter_done_sts         : 1;
+        u64 sexit_done_sts          : 1;
+        u64 reserved1               : 2;
+        u64 lt_mem_unlock_sts       : 1;
+        u64 lt_nodma_en_sts         : 1;
+        u64 lt_mem_config_lock_sts  : 1;
+        u64 lt_private_open_sts     : 1;
+        u64 reserved2               : 1;
+        u64 lt_nodma_cache_sts      : 1;
+        u64 lt_nodma_table_prot_sts : 1;
+        u64 lt_mem_config_ok_sts    : 1;
+    };
+} lt_sts_t;
+
+
+/*
+ * fns to read/write LT config regs
+ */
+
+/* returns proper addr (virt from fixmap or phys) depending on proc mode */
+extern u32 config_reg_base_addr(u32 base_phys);
+
+static inline u64 read_config_reg(u32 config_regs_base, u32 reg)
+{
+    /* these are MMIO so make sure compiler doesn't optimize */
+    return *(volatile u64 *)(config_reg_base_addr(config_regs_base) + reg);
+}
+
+static inline void write_config_reg(u32 config_regs_base, u32 reg, u64 val)
+{
+    /* these are MMIO so make sure compiler doesn't optimize */
+    *(volatile u64 *)(config_reg_base_addr(config_regs_base) + reg) = val;
+}
+
+static inline u64 read_pub_config_reg(u32 reg)
+{
+    return read_config_reg(LT_PUB_CONFIG_REGS_BASE, reg);
+}
+
+static inline void write_pub_config_reg(u32 reg, u64 val)
+{
+    write_config_reg(LT_PUB_CONFIG_REGS_BASE, reg, val);
+}
+
+static inline u64 read_priv_config_reg(u32 reg)
+{
+    return read_config_reg(LT_PRIV_CONFIG_REGS_BASE, reg);
+}
+
+static inline void write_priv_config_reg(u32 reg, u64 val)
+{
+    write_config_reg(LT_PRIV_CONFIG_REGS_BASE, reg, val);
+}
+
+/* this is a common use with annoying casting, so make it an inline */
+static inline lt_heap_t *get_lt_heap(void)
+{
+    return (lt_heap_t *)(unsigned long)read_pub_config_reg(LTCR_LT_HEAP_BASE);
+}
+
+#endif /* __ASM_X86_SMX_CONFIG_REGS_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/smx/mtrrs.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/smx/mtrrs.h	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,124 @@
+/*
+ * mtrrs.c: LT MTRR-related definitions
+ *
+ * Copyright (c) 2003-2006, 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 __ASM_X86_SMX_MTRRS_H__
+#define __ASM_X86_SMX_MTRRS_H__
+
+#include <asm/mtrr.h>
+
+enum var_mtrr_t {
+    MTRR_PHYS_BASE0_MSR = 0x200,
+    MTRR_PHYS_MASK0_MSR = 0x201,
+    MTRR_PHYS_BASE1_MSR = 0x202,
+    MTRR_PHYS_MASK1_MSR = 0x203,
+    MTRR_PHYS_BASE2_MSR = 0x204,
+    MTRR_PHYS_MASK2_MSR = 0x205,
+    MTRR_PHYS_BASE3_MSR = 0x206,
+    MTRR_PHYS_MASK3_MSR = 0x207,
+    MTRR_PHYS_BASE4_MSR = 0x208,
+    MTRR_PHYS_MASK4_MSR = 0x209,
+    MTRR_PHYS_BASE5_MSR = 0x20A,
+    MTRR_PHYS_MASK5_MSR = 0x20B,
+    MTRR_PHYS_BASE6_MSR = 0x20C,
+    MTRR_PHYS_MASK6_MSR = 0x20D,
+    MTRR_PHYS_BASE7_MSR = 0x20E,
+    MTRR_PHYS_MASK7_MSR = 0x20F
+};
+
+typedef union {
+    u64	raw;
+    struct {
+        u64 vcnt        : 8;    /* num variable MTRR pairs */
+        u64 fix         : 1;    /* fixed range MTRRs are supported */
+        u64 reserved1   : 1;
+        u64 wc          : 1;    /* write-combining mem type supported */
+        u64 reserved2   : 53;
+    };
+} mtrr_cap_t;
+
+typedef union {
+    u64	raw;
+    struct {
+        u64 type        : 8;
+        u64 reserved1   : 2;
+        u64 fe          : 1;    /* fixed MTRR enable */
+        u64 e           : 1;    /* (all) MTRR enable */
+        u64 reserved2   : 52;
+    };
+} mtrr_def_type_t;
+
+typedef union {
+    u64	raw;
+    struct {
+        u64 type      : 8;
+        u64 reserved1 : 4;
+        u64 base      : 24;
+        u64 reserved2 : 28;
+    };
+} mtrr_physbase_t;
+
+typedef union {
+    u64	raw;
+    struct {
+        u64 reserved1 : 11;
+        u64 v         : 1;      /* valid */
+        u64 mask      : 24;
+        u64 reserved2 : 28;
+    };
+} mtrr_physmask_t;
+
+/* current procs only have 8, so this should hold us for a while */
+#define MAX_VARIABLE_MTRRS      16
+
+typedef struct {
+    mtrr_def_type_t	    mtrr_def_type;
+    int	                num_var_mtrrs;
+    mtrr_physbase_t     mtrr_physbases[MAX_VARIABLE_MTRRS];
+    mtrr_physmask_t     mtrr_physmasks[MAX_VARIABLE_MTRRS];
+} mtrr_state_t;
+
+
+#endif /*__ASM_X86_SMX_MTRRS_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 041be3f6b38e -r 0b39e8a32d1f xen/include/asm-x86/smx/smx.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/smx/smx.h	Thu Sep 21 11:59:17 2006 +0800
@@ -0,0 +1,365 @@
+/*
+ * smx.h: LT SMX architecture-related definitions
+ *
+ * Copyright (c) 2003-2006, 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 __ASM_X86_SMX_SMX_H__
+#define __ASM_X86_SMX_SMX_H__
+
+#include <stdbool.h>
+#include <xen/types.h>
+#include <xen/multiboot.h>
+#include <asm/e820.h>
+#include <asm/smx/mtrrs.h>
+
+/*
+ * LT device space
+ */
+
+#define TPM_LOCALITY_BASE             0xfed40000
+#define NR_TPM_LOCALITY_PAGES         ((TPM_LOCALITY_1 - TPM_LOCALITY_0) >> \
+                                       PAGE_SHIFT)
+
+#define TPM_LOCALITY_0                TPM_LOCALITY_BASE
+#define TPM_LOCALITY_1                (TPM_LOCALITY_BASE | 0x1000)
+#define TPM_LOCALITY_2                (TPM_LOCALITY_BASE | 0x2000)
+/* these localities (3+4) are mostly not usable by Xen */
+#define TPM_LOCALITY_3                (TPM_LOCALITY_BASE | 0x3000)
+#define TPM_LOCALITY_4                (TPM_LOCALITY_BASE | 0x4000)
+
+#define TPM_LOCALITY_BASE_N(n)        (TPM_LOCALITY_BASE | ((n) << 12))
+
+
+/*
+ * data-passing structures contained in LT heap:
+ *   - BIOS to OS/loader
+ *   - OS/loader to MVMM
+ *   - OS/loader to SINIT
+ *   - SINIT to MVMM
+ */
+
+/*
+ * BIOS to OS/loader structure
+ *   - not used by current Xen
+ */
+typedef struct {
+    u32 version;           /* will be 0x00 */
+    u32 bios_sinit_size;
+} bios_os_data_v0_t;
+
+/*
+ * OS/loader to MVMM structure v1
+ *   - private to Xen (so can be any format we need)
+ */
+typedef struct {
+    u32	              version;           /* will be 0x01 */
+    mtrr_state_t      saved_mtrr_state;  /* saved prior to changes for SINIT */
+    multiboot_info_t *mbi;               /* needs to be restored to ebx */
+} os_mvmm_data_v1_t;
+
+/*
+ * OS/loader to SINIT structure v1
+ */
+typedef struct {
+    u32 version;           /* will be 0x01 */
+    u32 reserved;
+    u32 mvmm_ptab_lo;
+    u32 mvmm_ptab_hi;
+    u32 mvmm_size_lo;
+    u32 mvmm_size_hi;
+    u32 mvmm_hdr_base_lo;
+    u32 mvmm_hdr_base_hi;
+} os_sinit_data_v1_t;
+
+/*
+ * SINIT to MVMM structure v1
+ */
+#define MDR_MEMTYPE_GOOD                0x00
+#define MDR_MEMTYPE_SMM_OVERLAY         0x01
+#define MDR_MEMTYPE_SMM_NONOVERLAY      0x02
+#define MDR_MEMTYPE_PCIE_CONFIG_SPACE   0x03
+#define MDR_MEMTYPE_PROTECTED           0x04
+
+typedef struct __attribute__ ((packed)) {
+    u32 start_lo;
+    u32 start_hi;
+    u32 length_lo;
+    u32 length_hi;
+    u8  mem_type;
+    u8  reserved[7];
+} sinit_mdr_t;
+
+typedef struct {
+    u32          version;           /* will be 0x01 */
+    u32          num_mdrs;
+    sinit_mdr_t  mdrs[];
+} sinit_mvmm_data_v1_t;
+
+
+/*
+ * LT heap data format and field accessor fns
+ */
+
+/*
+ * offset                 length                      field
+ * ------                 ------                      -----
+ *  0                      8                          bios_os_data_size
+ *  8                      bios_os_data_size - 8      bios_os_data
+ *
+ *  bios_os_data_size      8                          os_mvmm_data_size
+ *  bios_os_data_size +    os_mvmm_data_size - 8      os_mvmm_data
+ *   8
+ *
+ *  bios_os_data_size +    8                          os_sinit_data_size
+ *   os_mvmm_data_size
+ *  bios_os_data_size +    os_sinit_data_size - 8     os_sinit_data
+ *   os_mvmm_data_size +
+ *   8
+ *
+ *  bios_os_data_size +    8                          sinit_mvmm_data_size
+ *   os_mvmm_data_size +
+ *   os_sinit_data_size
+ *  bios_os_data_size +    sinit_mvmm_data_size - 8   sinit_mvmm_data
+ *   os_mvmm_data_size +
+ *   os_sinit_data_size +
+ *   8
+ */
+
+typedef void   lt_heap_t;
+
+typedef struct {
+    u32    version;
+} lt_heap_data_hdr_t;
+
+static inline u64 *get_data_size_addr(void *data_start)
+{
+    return (u64 *)(data_start - sizeof(u64));
+}
+
+static inline u64 get_bios_os_data_size(lt_heap_t *lt_heap)
+{
+    return *(u64 *)lt_heap;
+}
+
+static inline lt_heap_data_hdr_t *get_bios_os_data_start(lt_heap_t *lt_heap)
+{
+    return (lt_heap_data_hdr_t *)((char*)lt_heap + sizeof(u64));
+}
+
+static inline u64 get_os_mvmm_data_size(lt_heap_t *lt_heap)
+{
+    return *(u64 *)(lt_heap + get_bios_os_data_size(lt_heap));
+}
+
+static inline lt_heap_data_hdr_t *get_os_mvmm_data_start(lt_heap_t *lt_heap)
+{
+    return (lt_heap_data_hdr_t *)(lt_heap + get_bios_os_data_size(lt_heap) +
+                                  sizeof(u64));
+}
+
+static inline u64 get_os_sinit_data_size(lt_heap_t *lt_heap)
+{
+    return *(u64 *)(lt_heap + get_bios_os_data_size(lt_heap) +
+                    get_os_mvmm_data_size(lt_heap));
+}
+
+static inline lt_heap_data_hdr_t *get_os_sinit_data_start(lt_heap_t *lt_heap)
+{
+    return (lt_heap_data_hdr_t *)(lt_heap + get_bios_os_data_size(lt_heap) +
+                                  get_os_mvmm_data_size(lt_heap) +
+                                  sizeof(u64));
+}
+
+static inline u64 get_sinit_mvmm_data_size(lt_heap_t *lt_heap)
+{
+    return *(u64 *)(lt_heap + get_bios_os_data_size(lt_heap) +
+                    get_os_mvmm_data_size(lt_heap) +
+                    get_os_sinit_data_size(lt_heap));
+}
+
+static inline lt_heap_data_hdr_t *get_sinit_mvmm_data_start(lt_heap_t *lt_heap)
+{
+    return (lt_heap_data_hdr_t *)(lt_heap + get_bios_os_data_size(lt_heap) +
+                                  get_os_mvmm_data_size(lt_heap) +
+                                  get_os_sinit_data_size(lt_heap) +
+                                  sizeof(u64));
+}
+
+
+/*
+ * MVMM header structure
+ *   describes an MVMM for SINIT and OS/loader SW
+ */
+typedef struct {
+    u32  guid[4];
+    u32  length;
+    u32  version;
+    u32  entry_point;
+    u32  req_mem_size;
+    u32  features;
+} mvmm_hdr_t;
+
+
+/*
+ * RLP JOIN structure for GETSEC[WAKEUP]
+ */
+typedef struct {
+    u32	gdt_limit;
+    u32	gdt_base;
+    u32	seg_sel;               /* cs (ds, es, ss are seg_sel+8) */
+    u32	entry_point;           /* phys addr */
+} mvmm_join_t;
+
+/*
+ * GETSEC[] instructions
+ */
+
+/* GETSEC instruction opcode */
+#define IA32_GETSEC_OPCODE		".byte 0x0f,0x37"
+
+/* GETSEC leaf function codes */
+#define IA32_GETSEC_CAPABILITIES	0
+#define IA32_GETSEC_SENTER		    4
+#define IA32_GETSEC_SEXIT		    5
+#define IA32_GETSEC_PARAMETERS		6
+#define IA32_GETSEC_SMCTRL          7
+#define IA32_GETSEC_WAKEUP		    8
+
+/*
+ * GETSEC[] leaf functions
+ */
+
+typedef union {
+    u32 _raw;
+    struct {
+        u32 chipset_present  : 1;
+        u32 undefined1	     : 1;
+        u32 enteraccs	     : 1;
+        u32 exitac	         : 1;
+        u32 senter	         : 1;
+        u32 sexit	         : 1;
+        u32 parameters	     : 1;
+        u32 smctrl	         : 1;
+        u32 wakeup	         : 1;
+        u32 undefined9	     : 22;
+        u32 extended_leafs   : 1;
+    };
+} capabilities_t;
+
+static inline capabilities_t __getsec_capabilities(u32 index)
+{
+    u32 cap;
+    __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+              : "=a"(cap)
+              : "a"(IA32_GETSEC_CAPABILITIES), "b"(index));
+    return (capabilities_t)cap;
+}
+
+static inline void __getsec_senter(u32 sinit_base, u32 sinit_size) 
+{
+    __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+			  :
+			  : "a"(IA32_GETSEC_SENTER),
+			    "b"(sinit_base),
+			    "c"(sinit_size),
+			    "d"(0x0));
+}
+
+static inline void __getsec_sexit(void) 
+{
+    __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+                          : : "a"(IA32_GETSEC_SEXIT));
+}
+
+static inline void __getsec_wakeup(void) 
+{
+    __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+                          : : "a"(IA32_GETSEC_WAKEUP));
+}
+
+static inline void __getsec_smctrl(void)
+{
+    __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+                          : : "a"(IA32_GETSEC_SMCTRL), "b"(0x0));
+}
+
+static inline void __getsec_parameters(u32 index, int* param_type,
+                                     u32* peax, u32* pebx, u32* pecx) 
+{
+    u32 eax=0, ebx=0, ecx=0;
+    __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+                          : "=a"(eax), "=b"(ebx), "=c"(ecx)
+                          : "a"(IA32_GETSEC_PARAMETERS), "b"(index));
+
+    if ( param_type != NULL )   *param_type = eax & 0x1f;
+    if ( peax != NULL )         *peax = eax;
+    if ( pebx != NULL )         *pebx = ebx;
+    if ( pecx != NULL )         *pecx = ecx;
+}
+
+
+/* used for debugging in very early boot environment */
+void early_serial_printk(const char *fmt, ...);
+
+/* used in shutdown.c */
+extern void smx_scrub_proc(void);
+extern void smx_scrub_mem(void);
+extern void smx_teardown(bool is_bsp);
+
+/* manage MTRRs for launch of AC module (SINIT) */
+void save_mtrrs(mtrr_state_t *saved_state);
+void restore_mtrrs(mtrr_state_t *saved_state);
+int set_mem_type(void *base, u32 size, u32 mem_type);
+void set_all_mtrrs(bool enable);
+
+int smx_reserve_memory(struct e820map *map);
+
+bool smx_in_prot_env(void);
+
+unsigned long smx_rlp_restart(int cpu);
+
+void display_errors(void);
+
+int verify_tpm_ready(void);
+
+#endif /* __ASM_X86_SMX_SMX_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-07-12 16:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-12 21:07 [Xense-devel] [RFC][PATCH][UPDATED] Intel(R) LaGrande Technology support Jonathan M. McCune
2007-04-12 21:52 ` Cihula, Joseph
2007-07-11 20:51 ` [RFC][PATCH][0/2] Intel(r) Trusted Execution Technology Jonathan M. McCune
2007-07-12 13:40   ` Jonathan M. McCune
2007-07-12 16:54     ` Cihula, Joseph
  -- strict thread matches above, loose matches on Subject: below --
2006-09-22 19:00 [RFC][PATCH][UPDATED] Intel(R) LaGrande Technology support Cihula, Joseph
2006-09-23 17:01 ` [Xense-devel] " Leendert Van Doorn

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.