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
|