WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] to fix the bug for tboot on x86_32 brought by c/s 19

To: keir.fraser@xxxxxxxxxxxxx, xen-devel@xxxxxxxxxxxxxxxxxxx, "Cihula, Joseph" <joseph.cihula@xxxxxxxxx>, xudong.hao@xxxxxxxxx
Subject: [Xen-devel] [PATCH] to fix the bug for tboot on x86_32 brought by c/s 19914 and 19922
From: Shane Wang <shane.wang@xxxxxxxxx>
Date: Fri, 06 Nov 2009 19:29:37 +0800
Cc:
Delivery-date: Fri, 06 Nov 2009 03:30:15 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 2.0.0.22 (Windows/20090605)
The changesets 19914 and 19922 remove the bitmap for boot allocator, which causes first_valid_mfn is reduced and starts from the end of xen. On the other hand, on x86_64, the xen heap is got considering e820 table, while on x86_32 the xen heap is specified to be < xenheap_phys_end. This range overlaps tboot range. So, the tboot range is scrubbed by scrub_heap_pages() during start_xen() on x86_32. Then the result is that for TXT support on x86_32, shutdown/reboot/Sx doesn't work properly. (i.e. hang)

This patch is to fix that by reserving tboot range as "inuse" in xen heap on x86_32. Then xen code will not touch the range.

Signed-off-by: Shane Wang <shane.wang@xxxxxxxxx>
---

diff -r e351f4cedded xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/arch/x86/setup.c      Fri Nov 06 10:29:44 2009 -0800
@@ -1066,6 +1066,9 @@ void __init __start_xen(unsigned long mb
     if ( !tboot_protect_mem_regions() )
         panic("Could not protect TXT memory regions\n");

+    if ( !tboot_reserve_range() )
+        panic("Could not reserve tboot range, tboot has been overwritten\n");
+
     /* Create initial domain 0. */
     dom0 = domain_create(0, DOMCRF_s3_integrity, DOM0_SSIDREF);
     if ( (dom0 == NULL) || (alloc_dom0_vcpu0() == NULL) )
diff -r e351f4cedded xen/arch/x86/tboot.c
--- a/xen/arch/x86/tboot.c      Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/arch/x86/tboot.c      Fri Nov 06 10:29:44 2009 -0800
@@ -137,6 +137,24 @@ void __init tboot_probe(void)
                       TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_SIZE);
 }

+int __init tboot_reserve_range(void)
+{
+#if defined(CONFIG_X86_32)
+    /*
+     * reserve tboot range (from MLE page table to tboot end)
+     * from xenheap for X86_32
+     */
+    unsigned long mfn;
+    for ( mfn = PFN_DOWN(g_tboot_shared->tboot_base - 3*PAGE_SIZE);
+          mfn < PFN_DOWN(g_tboot_shared->tboot_base)
+                + PFN_UP(g_tboot_shared->tboot_size);
+          mfn++ )
+        if ( reserve_page_as_used(mfn) )
+            return 0;
+#endif
+    return 1;
+}
+
 /* definitions from xen/drivers/passthrough/vtd/iommu.h
  * used to walk through vtd page tables */
 #define LEVEL_STRIDE (9)
@@ -195,16 +213,16 @@ static void update_pagetable_mac(vmac_ct
         }
     }
 }
-
-static void tboot_gen_domain_integrity(const uint8_t key[TB_KEY_SIZE],
-                                       vmac_t *mac)
+
+static void tboot_mac_domain(void)
 {
     struct domain *d;
     struct page_info *page;
     uint8_t nonce[16] = {};
     vmac_ctx_t ctx;

-    vmac_set_key((uint8_t *)key, &ctx);
+    memset(&domain_mac, 0, sizeof(vmac_t));
+    vmac_set_key((uint8_t *)g_tboot_shared->s3_key, &ctx);
     for_each_domain( d )
     {
         if ( !d->arch.s3_integrity )
@@ -228,22 +246,52 @@ static void tboot_gen_domain_integrity(c
     /* MAC all shadow page tables */
     update_pagetable_mac(&ctx);

-    *mac = vmac(NULL, 0, nonce, NULL, &ctx);
+    domain_mac = vmac(NULL, 0, nonce, NULL, &ctx);

-    printk("MAC for domains is: 0x%08"PRIx64"\n", *mac);
+    printk("MAC for domains is: 0x%08"PRIx64"\n", domain_mac);

     /* wipe ctx to ensure key is not left in memory */
     memset(&ctx, 0, sizeof(ctx));
 }

-static void tboot_gen_xenheap_integrity(const uint8_t key[TB_KEY_SIZE],
-                                        vmac_t *mac)
+static void tboot_add_mac_region(uint64_t start, uint64_t end)
+{
+    tboot_mac_region_t *mr;
+
+    if ( end <= start )
+        return;
+
+    ASSERT(g_tboot_shared->num_mac_regions < MAX_TB_MAC_REGIONS);
+
+    mr = &g_tboot_shared->mac_regions[g_tboot_shared->num_mac_regions++];
+    mr->start = start;
+    mr->size = end - mr->start;
+}
+
+#if defined(CONFIG_X86_32)
+static void tboot_mac_xenheap(void)
+{
+    uint64_t start, end;
+
+    start = g_tboot_shared->tboot_base - 3*PAGE_SIZE; /* from MLE page table */
+    end = g_tboot_shared->tboot_base + g_tboot_shared->tboot_size;
+
+    if ( start < xenheap_phys_end ) {
+        if ( __pa(&_end) < start )
+            tboot_add_mac_region(__pa(&_end), start);
+        if ( end < xenheap_phys_end )
+            tboot_add_mac_region(end, xenheap_phys_end);
+    }
+}
+#else /* !CONFIG_X86_32 */
+static void tboot_mac_xenheap(void)
 {
     unsigned long mfn;
     uint8_t nonce[16] = {};
     vmac_ctx_t ctx;

-    vmac_set_key((uint8_t *)key, &ctx);
+    memset(&xenheap_mac, 0, sizeof(vmac_t));
+    vmac_set_key((uint8_t *)g_tboot_shared->s3_key, &ctx);
     for ( mfn = 0; mfn < max_page; mfn++ )
     {
         struct page_info *page = __mfn_to_page(mfn);
@@ -255,25 +303,26 @@ static void tboot_gen_xenheap_integrity(
             vmac_update((uint8_t *)pg, PAGE_SIZE, &ctx);
         }
     }
-    *mac = vmac(NULL, 0, nonce, NULL, &ctx);
+    xenheap_mac = vmac(NULL, 0, nonce, NULL, &ctx);

-    printk("MAC for xenheap is: 0x%08"PRIx64"\n", *mac);
+    printk("MAC for xenheap is: 0x%08"PRIx64"\n", xenheap_mac);

     /* wipe ctx to ensure key is not left in memory */
     memset(&ctx, 0, sizeof(ctx));
 }
+#endif

-static void tboot_gen_frametable_integrity(const uint8_t key[TB_KEY_SIZE],
-                                           vmac_t *mac)
+static void tboot_mac_frametable(void)
 {
     uint8_t nonce[16] = {};
     vmac_ctx_t ctx;

-    vmac_set_key((uint8_t *)key, &ctx);
-    *mac = vmac((uint8_t *)frame_table,
+    memset(&frametable_mac, 0, sizeof(vmac_t));
+    vmac_set_key((uint8_t *)g_tboot_shared->s3_key, &ctx);
+    frametable_mac = vmac((uint8_t *)frame_table,
                 PFN_UP(max_pdx * sizeof(*frame_table)), nonce, NULL, &ctx);

-    printk("MAC for frametable is: 0x%08"PRIx64"\n", *mac);
+    printk("MAC for frametable is: 0x%08"PRIx64"\n", frametable_mac);

     /* wipe ctx to ensure key is not left in memory */
     memset(&ctx, 0, sizeof(ctx));
@@ -311,31 +360,32 @@ void tboot_shutdown(uint32_t shutdown_ty
         /*
          * Xen regions for tboot to MAC
          */
-        g_tboot_shared->num_mac_regions = 4;
+        g_tboot_shared->num_mac_regions = 0;
         /* S3 resume code (and other real mode trampoline code) */
-        g_tboot_shared->mac_regions[0].start = bootsym_phys(trampoline_start);
-        g_tboot_shared->mac_regions[0].size = bootsym_phys(trampoline_end) -
-                                              bootsym_phys(trampoline_start);
+        tboot_add_mac_region(bootsym_phys(trampoline_start),
+                             bootsym_phys(trampoline_end));
+
         /* hypervisor code + data */
-        g_tboot_shared->mac_regions[1].start = (uint64_t)__pa(&_stext);
-        g_tboot_shared->mac_regions[1].size = __pa(&__init_begin) -
-                                              __pa(&_stext);
+        tboot_add_mac_region((uint64_t)__pa(&_stext),
+                             (uint64_t)__pa(&__init_begin));
+
         /* per-cpu data */
-        g_tboot_shared->mac_regions[2].start = 
(uint64_t)__pa(&__per_cpu_start);
-        g_tboot_shared->mac_regions[2].size =
-            (((uint64_t)last_cpu(cpu_possible_map) + 1) << PERCPU_SHIFT);
+        tboot_add_mac_region((uint64_t)__pa(&__per_cpu_start),
+            (uint64_t)__pa(&__per_cpu_start)
+            + (((uint64_t)last_cpu(cpu_possible_map) + 1) << PERCPU_SHIFT));
+
         /* bss */
-        g_tboot_shared->mac_regions[3].start = (uint64_t)__pa(&__bss_start);
-        g_tboot_shared->mac_regions[3].size = __pa(&_end) - __pa(&__bss_start);
+        tboot_add_mac_region((uint64_t)__pa(&__bss_start),
+                             (uint64_t)__pa(&_end));

         /*
          * MAC domains and other Xen memory
          */
         /* Xen has no better entropy source for MAC key than tboot's */
         /* MAC domains first in case it perturbs xenheap */
-        tboot_gen_domain_integrity(g_tboot_shared->s3_key, &domain_mac);
-        tboot_gen_frametable_integrity(g_tboot_shared->s3_key, 
&frametable_mac);
-        tboot_gen_xenheap_integrity(g_tboot_shared->s3_key, &xenheap_mac);
+        tboot_mac_domain();
+        tboot_mac_frametable();
+        tboot_mac_xenheap();
     }

     write_ptbase(idle_vcpu[0]);
@@ -452,15 +502,18 @@ int tboot_s3_resume(void)
         return 0;

     /* need to do these in reverse order of shutdown */
-    tboot_gen_xenheap_integrity(g_tboot_shared->s3_key, &mac);
+    memcpy(&mac, &xenheap_mac, sizeof(vmac_t));
+    tboot_mac_xenheap();
     if ( mac != xenheap_mac )
         return -1;

-    tboot_gen_frametable_integrity(g_tboot_shared->s3_key, &mac);
+    memcpy(&mac, &frametable_mac, sizeof(vmac_t));
+    tboot_mac_frametable();
     if ( mac != frametable_mac )
         return -2;

-    tboot_gen_domain_integrity(g_tboot_shared->s3_key, &mac);
+    memcpy(&mac, &domain_mac, sizeof(vmac_t));
+    tboot_mac_domain();
     if ( mac != domain_mac )
         return -3;

diff -r e351f4cedded xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/common/page_alloc.c   Fri Nov 06 10:29:44 2009 -0800
@@ -383,14 +383,15 @@ static struct page_info *alloc_heap_page
     return pg;
 }

-/* Remove any offlined page in the buddy pointed to by head. */
-static int reserve_offlined_page(struct page_info *head)
+/* Remove page from the free pages in the buddy pointed to by head */
+static int reserve_free_page(struct page_info *head, unsigned long pg_state)
 {
     unsigned int node = phys_to_nid(page_to_maddr(head));
     int zone = page_to_zone(head), i, head_order = PFN_ORDER(head), count = 0;
     struct page_info *cur_head;
     int cur_order;

+    ASSERT((pg_state == PGC_state_offlined) || (pg_state == PGC_state_inuse));
     ASSERT(spin_is_locked(&heap_lock));

     cur_head = head;
@@ -402,7 +403,7 @@ static int reserve_offlined_page(struct
         struct page_info *pg;
         int next_order;

-        if ( page_state_is(cur_head, offlined) )
+        if ( (cur_head->count_info & PGC_state) == pg_state )
         {
             cur_head++;
             continue;
@@ -420,7 +421,7 @@ static int reserve_offlined_page(struct
             for ( i = (1 << cur_order), pg = cur_head + (1 << cur_order );
                   i < (1 << next_order);
                   i++, pg++ )
-                if ( page_state_is(pg, offlined) )
+                if ( (pg->count_info & PGC_state) == pg_state )
                     break;
             if ( i == ( 1 << next_order) )
             {
@@ -441,19 +442,30 @@ static int reserve_offlined_page(struct

     for ( cur_head = head; cur_head < head + ( 1UL << head_order); cur_head++ )
     {
-        if ( !page_state_is(cur_head, offlined) )
+        if ( !((cur_head->count_info & PGC_state) == pg_state) )
             continue;

         avail[node][zone]--;

-        page_list_add_tail(cur_head,
-                           test_bit(_PGC_broken, &cur_head->count_info) ?
-                           &page_broken_list : &page_offlined_list);
+        /* additional adding tail for offlined */
+        if ( pg_state == PGC_state_offlined )
+            page_list_add_tail(cur_head,
+                               test_bit(_PGC_broken, &cur_head->count_info) ?
+                               &page_broken_list : &page_offlined_list);

         count++;
     }

     return count;
+}
+
+/* Remove any offlined page in the buddy pointed to by head. */
+static int reserve_offlined_page(struct page_info *head)
+{
+    if ( head == NULL )
+        return -EINVAL;
+
+    return reserve_free_page(head, PGC_state_offlined);
 }

 /* Free 2^@order set of pages. */
@@ -577,7 +589,7 @@ static unsigned long mark_page_offline(s
     return y;
 }

-static int reserve_heap_page(struct page_info *pg)
+static struct page_info* get_heap_page_head(struct page_info *pg)
 {
     struct page_info *head = NULL;
     unsigned int i, node = phys_to_nid(page_to_maddr(pg));
@@ -594,12 +606,11 @@ static int reserve_heap_page(struct page
         {
             if ( (head <= pg) &&
                  (head + (1UL << i) > pg) )
-                return reserve_offlined_page(head);
+                return head;
         }
     }

-    return -EINVAL;
-
+    return NULL;
 }

 int offline_page(unsigned long mfn, int broken, uint32_t *status)
@@ -643,7 +654,7 @@ int offline_page(unsigned long mfn, int
     if ( page_state_is(pg, free) )
     {
         /* Free pages are reserve directly */
-        reserve_heap_page(pg);
+        reserve_offlined_page(get_heap_page_head(pg));
         *status = PG_OFFLINE_OFFLINED;
     }
     else if ( page_state_is(pg, offlined) )
@@ -742,6 +753,50 @@ unsigned int online_page(unsigned long m
     return ret;
 }

+int reserve_page_as_used(unsigned long mfn)
+{
+    struct page_info *head, *pg;
+    unsigned long nx, x, y;
+    int ret;
+
+    if ( mfn > max_page )
+    {
+        dprintk(XENLOG_WARNING,
+                "try to reserve page out of range %lx\n", mfn);
+        return -EINVAL;
+    }
+
+    pg = mfn_to_page(mfn);
+    if ( !page_state_is(pg, free) )
+        return -EINVAL;
+
+    spin_lock(&heap_lock);
+
+    /* mark the page as inuse */
+    y = pg->count_info;
+    do {
+        nx = x = y;
+
+        nx &= ~PGC_state;
+        nx |= PGC_state_inuse;
+
+        if ( x == nx )
+            break;
+    } while ( (y = cmpxchg(&pg->count_info, x, nx)) != x );
+
+    head = get_heap_page_head(pg);
+    if ( head == NULL )
+    {
+        spin_unlock(&heap_lock);
+        ret = -EINVAL;
+    }
+
+    reserve_free_page(head, PGC_state_inuse);
+    spin_unlock(&heap_lock);
+
+    return 0;
+}
+
 int query_page_offline(unsigned long mfn, uint32_t *status)
 {
     struct page_info *pg;
diff -r e351f4cedded xen/include/asm-x86/tboot.h
--- a/xen/include/asm-x86/tboot.h       Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/include/asm-x86/tboot.h       Fri Nov 06 10:29:44 2009 -0800
@@ -114,6 +114,7 @@ extern tboot_shared_t *g_tboot_shared;
 extern tboot_shared_t *g_tboot_shared;

 void tboot_probe(void);
+int tboot_reserve_range(void);
 void tboot_shutdown(uint32_t shutdown_type);
 int tboot_in_measured_env(void);
 int tboot_protect_mem_regions(void);
diff -r e351f4cedded xen/include/xen/mm.h
--- a/xen/include/xen/mm.h      Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/include/xen/mm.h      Fri Nov 06 10:29:44 2009 -0800
@@ -62,6 +62,7 @@ unsigned int online_page(unsigned long m
 unsigned int online_page(unsigned long mfn, uint32_t *status);
 int offline_page(unsigned long mfn, int broken, uint32_t *status);
 int query_page_offline(unsigned long mfn, uint32_t *status);
+int reserve_page_as_used(unsigned long mfn);

 void scrub_heap_pages(void);


diff -r e351f4cedded xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/arch/x86/setup.c      Fri Nov 06 10:29:44 2009 -0800
@@ -1066,6 +1066,9 @@ void __init __start_xen(unsigned long mb
     if ( !tboot_protect_mem_regions() )
         panic("Could not protect TXT memory regions\n");
 
+    if ( !tboot_reserve_range() )
+        panic("Could not reserve tboot range, tboot has been overwritten\n");
+
     /* Create initial domain 0. */
     dom0 = domain_create(0, DOMCRF_s3_integrity, DOM0_SSIDREF);
     if ( (dom0 == NULL) || (alloc_dom0_vcpu0() == NULL) )
diff -r e351f4cedded xen/arch/x86/tboot.c
--- a/xen/arch/x86/tboot.c      Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/arch/x86/tboot.c      Fri Nov 06 10:29:44 2009 -0800
@@ -137,6 +137,24 @@ void __init tboot_probe(void)
                       TXT_PUB_CONFIG_REGS_BASE + TXTCR_SINIT_SIZE);
 }
 
+int __init tboot_reserve_range(void)
+{
+#if defined(CONFIG_X86_32)
+    /* 
+     * reserve tboot range (from MLE page table to tboot end)
+     * from xenheap for X86_32
+     */
+    unsigned long mfn;
+    for ( mfn = PFN_DOWN(g_tboot_shared->tboot_base - 3*PAGE_SIZE);
+          mfn < PFN_DOWN(g_tboot_shared->tboot_base)
+                + PFN_UP(g_tboot_shared->tboot_size);
+          mfn++ )
+        if ( reserve_page_as_used(mfn) )
+            return 0;
+#endif
+    return 1;
+}
+
 /* definitions from xen/drivers/passthrough/vtd/iommu.h
  * used to walk through vtd page tables */
 #define LEVEL_STRIDE (9)
@@ -195,16 +213,16 @@ static void update_pagetable_mac(vmac_ct
         }
     }
 }
- 
-static void tboot_gen_domain_integrity(const uint8_t key[TB_KEY_SIZE],
-                                       vmac_t *mac)
+
+static void tboot_mac_domain(void)
 {
     struct domain *d;
     struct page_info *page;
     uint8_t nonce[16] = {};
     vmac_ctx_t ctx;
 
-    vmac_set_key((uint8_t *)key, &ctx);
+    memset(&domain_mac, 0, sizeof(vmac_t));
+    vmac_set_key((uint8_t *)g_tboot_shared->s3_key, &ctx);
     for_each_domain( d )
     {
         if ( !d->arch.s3_integrity )
@@ -228,22 +246,52 @@ static void tboot_gen_domain_integrity(c
     /* MAC all shadow page tables */
     update_pagetable_mac(&ctx);
 
-    *mac = vmac(NULL, 0, nonce, NULL, &ctx);
+    domain_mac = vmac(NULL, 0, nonce, NULL, &ctx);
 
-    printk("MAC for domains is: 0x%08"PRIx64"\n", *mac);
+    printk("MAC for domains is: 0x%08"PRIx64"\n", domain_mac);
 
     /* wipe ctx to ensure key is not left in memory */
     memset(&ctx, 0, sizeof(ctx));
 }
 
-static void tboot_gen_xenheap_integrity(const uint8_t key[TB_KEY_SIZE],
-                                        vmac_t *mac)
+static void tboot_add_mac_region(uint64_t start, uint64_t end)
+{
+    tboot_mac_region_t *mr;
+
+    if ( end <= start )
+        return;
+    
+    ASSERT(g_tboot_shared->num_mac_regions < MAX_TB_MAC_REGIONS);
+
+    mr = &g_tboot_shared->mac_regions[g_tboot_shared->num_mac_regions++];
+    mr->start = start;
+    mr->size = end - mr->start;
+}
+
+#if defined(CONFIG_X86_32)
+static void tboot_mac_xenheap(void)
+{
+    uint64_t start, end;
+
+    start = g_tboot_shared->tboot_base - 3*PAGE_SIZE; /* from MLE page table */
+    end = g_tboot_shared->tboot_base + g_tboot_shared->tboot_size;
+
+    if ( start < xenheap_phys_end ) {
+        if ( __pa(&_end) < start )
+            tboot_add_mac_region(__pa(&_end), start);
+        if ( end < xenheap_phys_end )
+            tboot_add_mac_region(end, xenheap_phys_end);
+    }
+}
+#else /* !CONFIG_X86_32 */
+static void tboot_mac_xenheap(void)
 {
     unsigned long mfn;
     uint8_t nonce[16] = {};
     vmac_ctx_t ctx;
 
-    vmac_set_key((uint8_t *)key, &ctx);
+    memset(&xenheap_mac, 0, sizeof(vmac_t));
+    vmac_set_key((uint8_t *)g_tboot_shared->s3_key, &ctx);
     for ( mfn = 0; mfn < max_page; mfn++ )
     {
         struct page_info *page = __mfn_to_page(mfn);
@@ -255,25 +303,26 @@ static void tboot_gen_xenheap_integrity(
             vmac_update((uint8_t *)pg, PAGE_SIZE, &ctx);
         }
     }
-    *mac = vmac(NULL, 0, nonce, NULL, &ctx);
+    xenheap_mac = vmac(NULL, 0, nonce, NULL, &ctx);
 
-    printk("MAC for xenheap is: 0x%08"PRIx64"\n", *mac);
+    printk("MAC for xenheap is: 0x%08"PRIx64"\n", xenheap_mac);
 
     /* wipe ctx to ensure key is not left in memory */
     memset(&ctx, 0, sizeof(ctx));
 }
+#endif
 
-static void tboot_gen_frametable_integrity(const uint8_t key[TB_KEY_SIZE],
-                                           vmac_t *mac)
+static void tboot_mac_frametable(void)
 {
     uint8_t nonce[16] = {};
     vmac_ctx_t ctx;
 
-    vmac_set_key((uint8_t *)key, &ctx);
-    *mac = vmac((uint8_t *)frame_table,
+    memset(&frametable_mac, 0, sizeof(vmac_t));
+    vmac_set_key((uint8_t *)g_tboot_shared->s3_key, &ctx);
+    frametable_mac = vmac((uint8_t *)frame_table,
                 PFN_UP(max_pdx * sizeof(*frame_table)), nonce, NULL, &ctx);
 
-    printk("MAC for frametable is: 0x%08"PRIx64"\n", *mac);
+    printk("MAC for frametable is: 0x%08"PRIx64"\n", frametable_mac);
 
     /* wipe ctx to ensure key is not left in memory */
     memset(&ctx, 0, sizeof(ctx));
@@ -311,31 +360,32 @@ void tboot_shutdown(uint32_t shutdown_ty
         /*
          * Xen regions for tboot to MAC
          */
-        g_tboot_shared->num_mac_regions = 4;
+        g_tboot_shared->num_mac_regions = 0;
         /* S3 resume code (and other real mode trampoline code) */
-        g_tboot_shared->mac_regions[0].start = bootsym_phys(trampoline_start);
-        g_tboot_shared->mac_regions[0].size = bootsym_phys(trampoline_end) -
-                                              bootsym_phys(trampoline_start);
+        tboot_add_mac_region(bootsym_phys(trampoline_start),
+                             bootsym_phys(trampoline_end));
+
         /* hypervisor code + data */
-        g_tboot_shared->mac_regions[1].start = (uint64_t)__pa(&_stext);
-        g_tboot_shared->mac_regions[1].size = __pa(&__init_begin) -
-                                              __pa(&_stext);
+        tboot_add_mac_region((uint64_t)__pa(&_stext),
+                             (uint64_t)__pa(&__init_begin));
+
         /* per-cpu data */
-        g_tboot_shared->mac_regions[2].start = 
(uint64_t)__pa(&__per_cpu_start);
-        g_tboot_shared->mac_regions[2].size =
-            (((uint64_t)last_cpu(cpu_possible_map) + 1) << PERCPU_SHIFT);
+        tboot_add_mac_region((uint64_t)__pa(&__per_cpu_start),
+            (uint64_t)__pa(&__per_cpu_start)
+            + (((uint64_t)last_cpu(cpu_possible_map) + 1) << PERCPU_SHIFT));
+
         /* bss */
-        g_tboot_shared->mac_regions[3].start = (uint64_t)__pa(&__bss_start);
-        g_tboot_shared->mac_regions[3].size = __pa(&_end) - __pa(&__bss_start);
+        tboot_add_mac_region((uint64_t)__pa(&__bss_start),
+                             (uint64_t)__pa(&_end));
 
         /*
          * MAC domains and other Xen memory
          */
         /* Xen has no better entropy source for MAC key than tboot's */
         /* MAC domains first in case it perturbs xenheap */
-        tboot_gen_domain_integrity(g_tboot_shared->s3_key, &domain_mac);
-        tboot_gen_frametable_integrity(g_tboot_shared->s3_key, 
&frametable_mac);
-        tboot_gen_xenheap_integrity(g_tboot_shared->s3_key, &xenheap_mac);
+        tboot_mac_domain();
+        tboot_mac_frametable();
+        tboot_mac_xenheap();
     }
 
     write_ptbase(idle_vcpu[0]);
@@ -452,15 +502,18 @@ int tboot_s3_resume(void)
         return 0;
 
     /* need to do these in reverse order of shutdown */
-    tboot_gen_xenheap_integrity(g_tboot_shared->s3_key, &mac);
+    memcpy(&mac, &xenheap_mac, sizeof(vmac_t));
+    tboot_mac_xenheap();
     if ( mac != xenheap_mac )
         return -1;
 
-    tboot_gen_frametable_integrity(g_tboot_shared->s3_key, &mac);
+    memcpy(&mac, &frametable_mac, sizeof(vmac_t));
+    tboot_mac_frametable();
     if ( mac != frametable_mac )
         return -2;
 
-    tboot_gen_domain_integrity(g_tboot_shared->s3_key, &mac);
+    memcpy(&mac, &domain_mac, sizeof(vmac_t));
+    tboot_mac_domain();
     if ( mac != domain_mac )
         return -3;
 
diff -r e351f4cedded xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/common/page_alloc.c   Fri Nov 06 10:29:44 2009 -0800
@@ -383,14 +383,15 @@ static struct page_info *alloc_heap_page
     return pg;
 }
 
-/* Remove any offlined page in the buddy pointed to by head. */
-static int reserve_offlined_page(struct page_info *head)
+/* Remove page from the free pages in the buddy pointed to by head */
+static int reserve_free_page(struct page_info *head, unsigned long pg_state)
 {
     unsigned int node = phys_to_nid(page_to_maddr(head));
     int zone = page_to_zone(head), i, head_order = PFN_ORDER(head), count = 0;
     struct page_info *cur_head;
     int cur_order;
 
+    ASSERT((pg_state == PGC_state_offlined) || (pg_state == PGC_state_inuse));
     ASSERT(spin_is_locked(&heap_lock));
 
     cur_head = head;
@@ -402,7 +403,7 @@ static int reserve_offlined_page(struct 
         struct page_info *pg;
         int next_order;
 
-        if ( page_state_is(cur_head, offlined) )
+        if ( (cur_head->count_info & PGC_state) == pg_state )
         {
             cur_head++;
             continue;
@@ -420,7 +421,7 @@ static int reserve_offlined_page(struct 
             for ( i = (1 << cur_order), pg = cur_head + (1 << cur_order );
                   i < (1 << next_order);
                   i++, pg++ )
-                if ( page_state_is(pg, offlined) )
+                if ( (pg->count_info & PGC_state) == pg_state )
                     break;
             if ( i == ( 1 << next_order) )
             {
@@ -441,19 +442,30 @@ static int reserve_offlined_page(struct 
 
     for ( cur_head = head; cur_head < head + ( 1UL << head_order); cur_head++ )
     {
-        if ( !page_state_is(cur_head, offlined) )
+        if ( !((cur_head->count_info & PGC_state) == pg_state) )
             continue;
 
         avail[node][zone]--;
 
-        page_list_add_tail(cur_head,
-                           test_bit(_PGC_broken, &cur_head->count_info) ?
-                           &page_broken_list : &page_offlined_list);
+        /* additional adding tail for offlined */
+        if ( pg_state == PGC_state_offlined )
+            page_list_add_tail(cur_head,
+                               test_bit(_PGC_broken, &cur_head->count_info) ?
+                               &page_broken_list : &page_offlined_list);
 
         count++;
     }
 
     return count;
+}
+
+/* Remove any offlined page in the buddy pointed to by head. */
+static int reserve_offlined_page(struct page_info *head)
+{
+    if ( head == NULL )
+        return -EINVAL;
+
+    return reserve_free_page(head, PGC_state_offlined);
 }
 
 /* Free 2^@order set of pages. */
@@ -577,7 +589,7 @@ static unsigned long mark_page_offline(s
     return y;
 }
 
-static int reserve_heap_page(struct page_info *pg)
+static struct page_info* get_heap_page_head(struct page_info *pg)
 {
     struct page_info *head = NULL;
     unsigned int i, node = phys_to_nid(page_to_maddr(pg));
@@ -594,12 +606,11 @@ static int reserve_heap_page(struct page
         {
             if ( (head <= pg) &&
                  (head + (1UL << i) > pg) )
-                return reserve_offlined_page(head);
+                return head;
         }
     }
 
-    return -EINVAL;
-
+    return NULL;
 }
 
 int offline_page(unsigned long mfn, int broken, uint32_t *status)
@@ -643,7 +654,7 @@ int offline_page(unsigned long mfn, int 
     if ( page_state_is(pg, free) )
     {
         /* Free pages are reserve directly */
-        reserve_heap_page(pg);
+        reserve_offlined_page(get_heap_page_head(pg));
         *status = PG_OFFLINE_OFFLINED;
     }
     else if ( page_state_is(pg, offlined) )
@@ -742,6 +753,50 @@ unsigned int online_page(unsigned long m
     return ret;
 }
 
+int reserve_page_as_used(unsigned long mfn)
+{
+    struct page_info *head, *pg;
+    unsigned long nx, x, y;
+    int ret;
+
+    if ( mfn > max_page )
+    {
+        dprintk(XENLOG_WARNING,
+                "try to reserve page out of range %lx\n", mfn);
+        return -EINVAL;
+    }
+
+    pg = mfn_to_page(mfn);
+    if ( !page_state_is(pg, free) )
+        return -EINVAL;
+
+    spin_lock(&heap_lock);
+
+    /* mark the page as inuse */
+    y = pg->count_info;
+    do {
+        nx = x = y;
+
+        nx &= ~PGC_state;
+        nx |= PGC_state_inuse;
+
+        if ( x == nx )
+            break;
+    } while ( (y = cmpxchg(&pg->count_info, x, nx)) != x );
+
+    head = get_heap_page_head(pg);
+    if ( head == NULL )
+    {
+        spin_unlock(&heap_lock);
+        ret = -EINVAL;
+    }
+
+    reserve_free_page(head, PGC_state_inuse);
+    spin_unlock(&heap_lock);
+
+    return 0;
+}
+    
 int query_page_offline(unsigned long mfn, uint32_t *status)
 {
     struct page_info *pg;
diff -r e351f4cedded xen/include/asm-x86/tboot.h
--- a/xen/include/asm-x86/tboot.h       Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/include/asm-x86/tboot.h       Fri Nov 06 10:29:44 2009 -0800
@@ -114,6 +114,7 @@ extern tboot_shared_t *g_tboot_shared;
 extern tboot_shared_t *g_tboot_shared;
 
 void tboot_probe(void);
+int tboot_reserve_range(void);
 void tboot_shutdown(uint32_t shutdown_type);
 int tboot_in_measured_env(void);
 int tboot_protect_mem_regions(void);
diff -r e351f4cedded xen/include/xen/mm.h
--- a/xen/include/xen/mm.h      Fri Nov 06 10:28:59 2009 -0800
+++ b/xen/include/xen/mm.h      Fri Nov 06 10:29:44 2009 -0800
@@ -62,6 +62,7 @@ unsigned int online_page(unsigned long m
 unsigned int online_page(unsigned long mfn, uint32_t *status);
 int offline_page(unsigned long mfn, int broken, uint32_t *status);
 int query_page_offline(unsigned long mfn, uint32_t *status);
+int reserve_page_as_used(unsigned long mfn);
 
 void scrub_heap_pages(void);
 
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel