562 lines
22 KiB
Diff
562 lines
22 KiB
Diff
Index: 2007-05-14/xen/arch/x86/mm.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/mm.c 2007-05-14 14:33:33.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/mm.c 2007-05-14 14:35:02.000000000 +0200
|
|
@@ -147,6 +147,14 @@ struct page_info *frame_table;
|
|
unsigned long max_page;
|
|
unsigned long total_pages;
|
|
|
|
+#define PAGE_CACHE_ATTRS (_PAGE_PAT|_PAGE_PCD|_PAGE_PWT)
|
|
+
|
|
+#define l1_disallow_mask(d) (!(d)->iomem_caps || \
|
|
+ !rangeset_is_empty((d)->iomem_caps) || \
|
|
+ !rangeset_is_empty((d)->arch.ioport_caps) ? \
|
|
+ L1_DISALLOW_MASK : \
|
|
+ L1_DISALLOW_MASK|PAGE_CACHE_ATTRS)
|
|
+
|
|
#ifdef CONFIG_COMPAT
|
|
l2_pgentry_t *compat_idle_pg_table_l2 = NULL;
|
|
#define l3_disallow_mask(d) (!is_pv_32on64_domain(d) ? \
|
|
@@ -265,9 +273,10 @@ void share_xen_page_with_guest(
|
|
|
|
spin_lock(&d->page_alloc_lock);
|
|
|
|
- /* The incremented type count pins as writable or read-only. */
|
|
page->u.inuse.type_info = (readonly ? PGT_none : PGT_writable_page);
|
|
- page->u.inuse.type_info |= PGT_validated | 1;
|
|
+ if ( readonly || d != dom_io )
|
|
+ /* The incremented type count pins as writable or read-only. */
|
|
+ page->u.inuse.type_info |= PGT_validated | 1;
|
|
|
|
page_set_owner(page, d);
|
|
wmb(); /* install valid domain ptr before updating refcnt. */
|
|
@@ -526,6 +535,74 @@ static int get_page_and_type_from_pagenr
|
|
return 1;
|
|
}
|
|
|
|
+static unsigned long get_writable_type(unsigned int flags)
|
|
+{
|
|
+ unsigned long type = PGT_none;
|
|
+
|
|
+ if ( flags & _PAGE_RW )
|
|
+ type = PGT_writable_page;
|
|
+ if ( flags & _PAGE_PWT )
|
|
+ type |= PGT_pwt_mask | PGT_writable_page;
|
|
+ if ( flags & _PAGE_PCD )
|
|
+ type |= PGT_pcd_mask | PGT_writable_page;
|
|
+#ifdef CONFIG_PAT
|
|
+ if ( flags & _PAGE_PAT )
|
|
+ type |= PGT_pat_mask | PGT_writable_page;
|
|
+#endif
|
|
+ BUG_ON(!(type & PGT_writable_page));
|
|
+
|
|
+ return type;
|
|
+}
|
|
+
|
|
+static int alloc_writable_page(struct page_info *page, unsigned long type)
|
|
+{
|
|
+ unsigned long mfn = page_to_mfn(page);
|
|
+ unsigned int flags = 0;
|
|
+ int ret;
|
|
+
|
|
+ if ( page_get_owner(page) == dom_io )
|
|
+ return 1;
|
|
+#ifdef __i386__
|
|
+ if ( mfn >= ((DIRECTMAP_VIRT_END - DIRECTMAP_VIRT_START) >> PAGE_SHIFT) )
|
|
+ return 1;
|
|
+#endif
|
|
+
|
|
+ if ( type & PGT_pwt_mask )
|
|
+ flags |= _PAGE_PWT;
|
|
+ if ( type & PGT_pcd_mask )
|
|
+ flags |= _PAGE_PCD;
|
|
+#ifdef CONFIG_PAT
|
|
+ if ( type & PGT_pat_mask )
|
|
+ flags |= _PAGE_PAT;
|
|
+#endif
|
|
+ ret = map_pages_to_xen((unsigned long)mfn_to_virt(mfn), mfn, 1,
|
|
+ PAGE_HYPERVISOR | flags);
|
|
+ if ( ret == 0 )
|
|
+ return 1;
|
|
+
|
|
+ MEM_LOG("Error %d changing cacheability of mfn %lx", ret, mfn);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void free_writable_page(struct page_info *page)
|
|
+{
|
|
+ unsigned long mfn = page_to_mfn(page);
|
|
+
|
|
+ if ( page_get_owner(page) == dom_io )
|
|
+ return;
|
|
+#ifdef __i386__
|
|
+ if ( mfn >= ((DIRECTMAP_VIRT_END - DIRECTMAP_VIRT_START) >> PAGE_SHIFT) )
|
|
+ return;
|
|
+#endif
|
|
+
|
|
+ if ( map_pages_to_xen((unsigned long)mfn_to_virt(mfn), mfn, 1,
|
|
+ PAGE_HYPERVISOR) )
|
|
+ {
|
|
+ printk("Reverting cacheability for %lx failed\n", mfn);
|
|
+ BUG();
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
* We allow root tables to map each other (a.k.a. linear page tables). It
|
|
* needs some special care with reference counts and access permissions:
|
|
@@ -586,15 +663,16 @@ get_page_from_l1e(
|
|
l1_pgentry_t l1e, struct domain *d)
|
|
{
|
|
unsigned long mfn = l1e_get_pfn(l1e);
|
|
+ unsigned int flags = l1e_get_flags(l1e);
|
|
struct page_info *page = mfn_to_page(mfn);
|
|
int okay;
|
|
|
|
- if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
|
|
+ if ( !(flags & _PAGE_PRESENT) )
|
|
return 1;
|
|
|
|
- if ( unlikely(l1e_get_flags(l1e) & L1_DISALLOW_MASK) )
|
|
+ if ( unlikely(flags & l1_disallow_mask(d)) )
|
|
{
|
|
- MEM_LOG("Bad L1 flags %x", l1e_get_flags(l1e) & L1_DISALLOW_MASK);
|
|
+ MEM_LOG("Bad L1 flags %x", flags & l1_disallow_mask(d));
|
|
return 0;
|
|
}
|
|
|
|
@@ -624,9 +702,9 @@ get_page_from_l1e(
|
|
* contribute to writeable mapping refcounts. (This allows the
|
|
* qemu-dm helper process in dom0 to map the domain's memory without
|
|
* messing up the count of "real" writable mappings.) */
|
|
- okay = (((l1e_get_flags(l1e) & _PAGE_RW) &&
|
|
+ okay = (((flags & (_PAGE_RW|PAGE_CACHE_ATTRS)) &&
|
|
!(unlikely(paging_mode_external(d) && (d != current->domain))))
|
|
- ? get_page_and_type(page, d, PGT_writable_page)
|
|
+ ? get_page_and_type(page, d, get_writable_type(flags))
|
|
: get_page(page, d));
|
|
if ( !okay )
|
|
{
|
|
@@ -819,7 +897,7 @@ void put_page_from_l1e(l1_pgentry_t l1e,
|
|
|
|
/* Remember we didn't take a type-count of foreign writable mappings
|
|
* to paging-external domains */
|
|
- if ( (l1e_get_flags(l1e) & _PAGE_RW) &&
|
|
+ if ( (l1e_get_flags(l1e) & (_PAGE_RW|PAGE_CACHE_ATTRS)) &&
|
|
!(unlikely((e != d) && paging_mode_external(e))) )
|
|
{
|
|
put_page_and_type(page);
|
|
@@ -1320,6 +1398,60 @@ static inline int update_intpte(intpte_t
|
|
_t ## e_get_intpte(_o), _t ## e_get_intpte(_n), \
|
|
(_m), (_v))
|
|
|
|
+/*
|
|
+ * Present->present transitions referencing the same page with old and new
|
|
+ * attributes resulting in (different) PGT_writable_page types and with the
|
|
+ * type use count being 1 must be special cased, as the transition would
|
|
+ * otherwise fail.
|
|
+ */
|
|
+static int transition_writable_page(l1_pgentry_t *pl1e, l1_pgentry_t ol1e,
|
|
+ l1_pgentry_t nl1e, unsigned long gl1mfn,
|
|
+ int do_cmpxchg)
|
|
+{
|
|
+ struct page_info *page = l1e_get_page(nl1e);
|
|
+ unsigned long type = get_writable_type(l1e_get_flags(ol1e));
|
|
+ unsigned long nx = type | 2;
|
|
+ unsigned long x = type | PGT_validated | 1;
|
|
+
|
|
+ if ( cmpxchg(&page->u.inuse.type_info, x, nx) == x )
|
|
+ {
|
|
+ /*
|
|
+ * The adjustment is now safe because the refcnt is 2 and validated
|
|
+ * bit is clear => non-free ops will spin or fail, and a racing free
|
|
+ * is illegal (will crash domain below).
|
|
+ */
|
|
+ type = get_writable_type(l1e_get_flags(nl1e));
|
|
+ if ( alloc_writable_page(page, type) )
|
|
+ {
|
|
+ x = nx;
|
|
+ nx = type | PGT_validated | 1;
|
|
+ if ( cmpxchg(&page->u.inuse.type_info, x, nx) == x )
|
|
+ {
|
|
+ if ( do_cmpxchg )
|
|
+ {
|
|
+ intpte_t t = l1e_get_intpte(ol1e);
|
|
+
|
|
+ if ( paging_cmpxchg_guest_entry(current,
|
|
+ &l1e_get_intpte(*pl1e),
|
|
+ &t,
|
|
+ l1e_get_intpte(nl1e),
|
|
+ _mfn(gl1mfn)) )
|
|
+ return t == l1e_get_intpte(ol1e);
|
|
+ }
|
|
+ else if ( UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, current) )
|
|
+ return 1;
|
|
+ }
|
|
+ domain_crash(current->domain);
|
|
+ return 0;
|
|
+ }
|
|
+ page->u.inuse.type_info |= PGT_validated;
|
|
+ /* Drop the extra reference. */
|
|
+ put_page_type(page);
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
/* Update the L1 entry at pl1e to new value nl1e. */
|
|
static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
|
|
unsigned long gl1mfn)
|
|
@@ -1339,19 +1471,31 @@ static int mod_l1_entry(l1_pgentry_t *pl
|
|
nl1e = l1e_from_pfn(gmfn_to_mfn(FOREIGNDOM, l1e_get_pfn(nl1e)),
|
|
l1e_get_flags(nl1e));
|
|
|
|
- if ( unlikely(l1e_get_flags(nl1e) & L1_DISALLOW_MASK) )
|
|
+ if ( unlikely(l1e_get_flags(nl1e) & l1_disallow_mask(d)) )
|
|
{
|
|
MEM_LOG("Bad L1 flags %x",
|
|
- l1e_get_flags(nl1e) & L1_DISALLOW_MASK);
|
|
+ l1e_get_flags(nl1e) & l1_disallow_mask(d));
|
|
return 0;
|
|
}
|
|
|
|
adjust_guest_l1e(nl1e, d);
|
|
|
|
- /* Fast path for identical mapping, r/w and presence. */
|
|
- if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) )
|
|
+ /* Fast path for identical mapping, r/w, cacheability, and presence. */
|
|
+ if ( !l1e_has_changed(ol1e, nl1e,
|
|
+ _PAGE_RW | _PAGE_PRESENT | PAGE_CACHE_ATTRS) )
|
|
return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, current);
|
|
|
|
+ if ( !l1e_has_changed(ol1e, nl1e, _PAGE_PRESENT) &&
|
|
+ (l1e_get_flags(ol1e) & (_PAGE_RW | PAGE_CACHE_ATTRS)) &&
|
|
+ (l1e_get_flags(nl1e) & (_PAGE_RW | PAGE_CACHE_ATTRS)) &&
|
|
+ mfn_valid(l1e_get_pfn(nl1e)) )
|
|
+ {
|
|
+ int ret = transition_writable_page(pl1e, ol1e, nl1e, gl1mfn, 0);
|
|
+
|
|
+ if ( ret >= 0 )
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
if ( unlikely(!get_page_from_l1e(nl1e, FOREIGNDOM)) )
|
|
return 0;
|
|
|
|
@@ -1546,10 +1690,13 @@ static int mod_l4_entry(struct domain *d
|
|
|
|
#endif
|
|
|
|
-int alloc_page_type(struct page_info *page, unsigned long type)
|
|
+static int alloc_page_type(struct page_info *page, unsigned long type)
|
|
{
|
|
struct domain *owner = page_get_owner(page);
|
|
|
|
+ if ( type & PGT_writable_page )
|
|
+ return alloc_writable_page(page, type);
|
|
+
|
|
/* A page table is dirtied when its type count becomes non-zero. */
|
|
if ( likely(owner != NULL) )
|
|
mark_dirty(owner, page_to_mfn(page));
|
|
@@ -1583,6 +1730,12 @@ void free_page_type(struct page_info *pa
|
|
struct domain *owner = page_get_owner(page);
|
|
unsigned long gmfn;
|
|
|
|
+ if ( type & PGT_writable_page )
|
|
+ {
|
|
+ free_writable_page(page);
|
|
+ return;
|
|
+ }
|
|
+
|
|
if ( likely(owner != NULL) )
|
|
{
|
|
/*
|
|
@@ -1652,11 +1805,13 @@ void put_page_type(struct page_info *pag
|
|
|
|
if ( unlikely((nx & PGT_count_mask) == 0) )
|
|
{
|
|
- if ( unlikely((nx & PGT_type_mask) <= PGT_l4_page_table) &&
|
|
+ if ( (unlikely((nx & PGT_type_mask) <= PGT_l4_page_table) ||
|
|
+ unlikely((nx & PGT_type_mask) > PGT_writable_page)) &&
|
|
likely(nx & PGT_validated) )
|
|
{
|
|
/*
|
|
- * Page-table pages must be unvalidated when count is zero. The
|
|
+ * Page-table pages and writable pages with non-default
|
|
+ * cacheability must be unvalidated when count is zero. The
|
|
* 'free' is safe because the refcnt is non-zero and validated
|
|
* bit is clear => other ops will spin or fail.
|
|
*/
|
|
@@ -1725,7 +1880,7 @@ int get_page_type(struct page_info *page
|
|
if ( unlikely(!cpus_empty(mask)) &&
|
|
/* Shadow mode: track only writable pages. */
|
|
(!shadow_mode_enabled(page_get_owner(page)) ||
|
|
- ((nx & PGT_type_mask) == PGT_writable_page)) )
|
|
+ (nx & PGT_writable_page)) )
|
|
{
|
|
perfc_incr(need_flush_tlb_flush);
|
|
flush_tlb_mask(mask);
|
|
@@ -3243,8 +3398,30 @@ static int ptwr_emulated_update(
|
|
ASSERT((page->u.inuse.type_info & PGT_count_mask) != 0);
|
|
ASSERT(page_get_owner(page) == d);
|
|
|
|
+ pl1e = (l1_pgentry_t *)((unsigned long)map_domain_page(mfn)
|
|
+ + (addr & ~PAGE_MASK));
|
|
+ ol1e = do_cmpxchg ? l1e_from_intpte(old) : *pl1e;
|
|
+
|
|
/* Check the new PTE. */
|
|
nl1e = l1e_from_intpte(val);
|
|
+ adjust_guest_l1e(nl1e, d);
|
|
+
|
|
+ if ( (l1e_get_flags(nl1e) & _PAGE_PRESENT) &&
|
|
+ !l1e_has_changed(ol1e, nl1e, _PAGE_PRESENT) &&
|
|
+ l1e_has_changed(ol1e, nl1e, _PAGE_RW | PAGE_CACHE_ATTRS) &&
|
|
+ (l1e_get_flags(ol1e) & (_PAGE_RW | PAGE_CACHE_ATTRS)) &&
|
|
+ (l1e_get_flags(nl1e) & (_PAGE_RW | PAGE_CACHE_ATTRS)) &&
|
|
+ mfn_valid(l1e_get_pfn(nl1e)) )
|
|
+ {
|
|
+ int ret = transition_writable_page(pl1e, ol1e, nl1e, mfn, do_cmpxchg);
|
|
+
|
|
+ if ( ret >= 0 )
|
|
+ {
|
|
+ unmap_domain_page(pl1e);
|
|
+ return ret ? X86EMUL_OKAY : X86EMUL_RETRY;
|
|
+ }
|
|
+ }
|
|
+
|
|
if ( unlikely(!get_page_from_l1e(nl1e, d)) )
|
|
{
|
|
if ( (CONFIG_PAGING_LEVELS >= 3) && is_pv_32bit_domain(d) &&
|
|
@@ -3263,21 +3440,17 @@ static int ptwr_emulated_update(
|
|
}
|
|
else
|
|
{
|
|
+ unmap_domain_page(pl1e);
|
|
MEM_LOG("ptwr_emulate: could not get_page_from_l1e()");
|
|
return X86EMUL_UNHANDLEABLE;
|
|
}
|
|
}
|
|
|
|
- adjust_guest_l1e(nl1e, d);
|
|
-
|
|
/* Checked successfully: do the update (write or cmpxchg). */
|
|
- pl1e = map_domain_page(mfn);
|
|
- pl1e = (l1_pgentry_t *)((unsigned long)pl1e + (addr & ~PAGE_MASK));
|
|
if ( do_cmpxchg )
|
|
{
|
|
int okay;
|
|
intpte_t t = old;
|
|
- ol1e = l1e_from_intpte(old);
|
|
|
|
okay = paging_cmpxchg_guest_entry(v, &l1e_get_intpte(*pl1e),
|
|
&t, val, _mfn(mfn));
|
|
@@ -3290,12 +3463,8 @@ static int ptwr_emulated_update(
|
|
return X86EMUL_CMPXCHG_FAILED;
|
|
}
|
|
}
|
|
- else
|
|
- {
|
|
- ol1e = *pl1e;
|
|
- if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v) )
|
|
- BUG();
|
|
- }
|
|
+ else if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v) )
|
|
+ BUG();
|
|
|
|
unmap_domain_page(pl1e);
|
|
|
|
@@ -3439,6 +3608,8 @@ int map_pages_to_xen(
|
|
if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
|
|
{
|
|
pl1e = alloc_xen_pagetable();
|
|
+ if ( pl1e == NULL )
|
|
+ return -ENOMEM;
|
|
clear_page(pl1e);
|
|
l2e_write(pl2e, l2e_from_pfn(virt_to_mfn(pl1e),
|
|
__PAGE_HYPERVISOR));
|
|
@@ -3446,6 +3617,8 @@ int map_pages_to_xen(
|
|
else if ( l2e_get_flags(*pl2e) & _PAGE_PSE )
|
|
{
|
|
pl1e = alloc_xen_pagetable();
|
|
+ if ( pl1e == NULL )
|
|
+ return -ENOMEM;
|
|
for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
|
|
l1e_write(&pl1e[i],
|
|
l1e_from_pfn(l2e_get_pfn(*pl2e) + i,
|
|
@@ -3464,6 +3637,28 @@ int map_pages_to_xen(
|
|
virt += 1UL << L1_PAGETABLE_SHIFT;
|
|
mfn += 1UL;
|
|
nr_mfns -= 1UL;
|
|
+
|
|
+ if ( !map_small_pages &&
|
|
+ flags == PAGE_HYPERVISOR &&
|
|
+ ( nr_mfns == 0 ||
|
|
+ ((((virt>>PAGE_SHIFT) | mfn) & ((1<<PAGETABLE_ORDER)-1)) == 0)) )
|
|
+ {
|
|
+ unsigned long base_mfn;
|
|
+
|
|
+ pl1e = l2e_to_l1e(*pl2e);
|
|
+ base_mfn = l1e_get_pfn(*pl1e);
|
|
+ for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++, pl1e++ )
|
|
+ if ( l1e_get_pfn(*pl1e) != base_mfn + i ||
|
|
+ l1e_get_flags(*pl1e) != flags )
|
|
+ break;
|
|
+ if ( i == L1_PAGETABLE_ENTRIES )
|
|
+ {
|
|
+ ol2e = *pl2e;
|
|
+ l2e_write(pl2e, l2e_from_pfn(base_mfn, flags|_PAGE_PSE));
|
|
+ local_flush_tlb_pge();
|
|
+ free_xen_pagetable(mfn_to_virt(l2e_get_pfn(ol2e)));
|
|
+ }
|
|
+ }
|
|
}
|
|
}
|
|
|
|
Index: 2007-05-14/xen/arch/x86/mm/shadow/common.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/mm/shadow/common.c 2007-05-14 08:28:38.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/mm/shadow/common.c 2007-05-14 14:35:02.000000000 +0200
|
|
@@ -1320,7 +1320,7 @@ static void sh_hash_audit_bucket(struct
|
|
/* Bad shadow flags on guest page? */
|
|
BUG_ON( !(gpg->shadow_flags & (1<<sp->type)) );
|
|
/* Bad type count on guest page? */
|
|
- if ( (gpg->u.inuse.type_info & PGT_type_mask) == PGT_writable_page
|
|
+ if ( (gpg->u.inuse.type_info & PGT_writable_page)
|
|
&& (gpg->u.inuse.type_info & PGT_count_mask) != 0 )
|
|
{
|
|
SHADOW_ERROR("MFN %#lx shadowed (by %#"PRI_mfn")"
|
|
Index: 2007-05-14/xen/arch/x86/mm/shadow/multi.c
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/arch/x86/mm/shadow/multi.c 2007-05-14 14:28:19.000000000 +0200
|
|
+++ 2007-05-14/xen/arch/x86/mm/shadow/multi.c 2007-05-14 14:35:02.000000000 +0200
|
|
@@ -4128,8 +4128,7 @@ audit_gfn_to_mfn(struct vcpu *v, gfn_t g
|
|
if ( !shadow_mode_translate(v->domain) )
|
|
return _mfn(gfn_x(gfn));
|
|
|
|
- if ( (mfn_to_page(gmfn)->u.inuse.type_info & PGT_type_mask)
|
|
- != PGT_writable_page )
|
|
+ if ( !(mfn_to_page(gmfn)->u.inuse.type_info & PGT_writable_page) )
|
|
return _mfn(gfn_x(gfn)); /* This is a paging-disabled shadow */
|
|
else
|
|
return gfn_to_mfn(v->domain, gfn_x(gfn));
|
|
Index: 2007-05-14/xen/include/asm-x86/mm.h
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/include/asm-x86/mm.h 2007-05-14 13:43:35.000000000 +0200
|
|
+++ 2007-05-14/xen/include/asm-x86/mm.h 2007-05-14 14:35:02.000000000 +0200
|
|
@@ -64,24 +64,35 @@ struct page_info
|
|
};
|
|
|
|
/* The following page types are MUTUALLY EXCLUSIVE. */
|
|
-#define PGT_none (0U<<29) /* no special uses of this page */
|
|
-#define PGT_l1_page_table (1U<<29) /* using this page as an L1 page table? */
|
|
-#define PGT_l2_page_table (2U<<29) /* using this page as an L2 page table? */
|
|
-#define PGT_l3_page_table (3U<<29) /* using this page as an L3 page table? */
|
|
-#define PGT_l4_page_table (4U<<29) /* using this page as an L4 page table? */
|
|
-#define PGT_gdt_page (5U<<29) /* using this page in a GDT? */
|
|
-#define PGT_ldt_page (6U<<29) /* using this page in an LDT? */
|
|
-#define PGT_writable_page (7U<<29) /* has writable mappings of this page? */
|
|
-#define PGT_type_mask (7U<<29) /* Bits 29-31. */
|
|
+#define PGT_none (0U<<28) /* no special uses of this page */
|
|
+#define PGT_l1_page_table (1U<<28) /* using this page as an L1 page table? */
|
|
+#define PGT_l2_page_table (2U<<28) /* using this page as an L2 page table? */
|
|
+#define PGT_l3_page_table (3U<<28) /* using this page as an L3 page table? */
|
|
+#define PGT_l4_page_table (4U<<28) /* using this page as an L4 page table? */
|
|
+#define PGT_gdt_page (5U<<28) /* using this page in a GDT? */
|
|
+#define PGT_ldt_page (6U<<28) /* using this page in an LDT? */
|
|
+#define PGT_writable_page (0x8U<<28) /* has writable mappings of this page? */
|
|
+#define PGT_pwt_mask (0x1U<<28) /* (l1e & _PAGE_PWT) mirror */
|
|
+#define PGT_pcd_mask (0x2U<<28) /* (l1e & _PAGE_PCD) mirror */
|
|
+#define PGT_wb_page (0x8U<<28) /* WB cached writable page? */
|
|
+#define PGT_wt_page (0x9U<<28) /* WT cached writable page? */
|
|
+#define PGT_ucm_page (0xAU<<28) /* UC- cached writable page? */
|
|
+#define PGT_uc_page (0xBU<<28) /* UC cached writable page? */
|
|
+#ifdef CONFIG_PAT
|
|
+#define PGT_pat_mask (0x4U<<28) /* (l1e & _PAGE_PAT) mirror */
|
|
+#define PGT_wc_page (0xCU<<28) /* WC cached writable page? */
|
|
+#define PGT_wp_page (0xDU<<28) /* WP cached writable page? */
|
|
+#endif
|
|
+#define PGT_type_mask (0xFU<<28) /* Bits 28-31. */
|
|
|
|
/* Owning guest has pinned this page to its current type? */
|
|
-#define _PGT_pinned 28
|
|
+#define _PGT_pinned 22
|
|
#define PGT_pinned (1U<<_PGT_pinned)
|
|
/* Has this page been validated for use as its current type? */
|
|
-#define _PGT_validated 27
|
|
+#define _PGT_validated 21
|
|
#define PGT_validated (1U<<_PGT_validated)
|
|
/* PAE only: is this an L2 page directory containing Xen-private mappings? */
|
|
-#define _PGT_pae_xen_l2 26
|
|
+#define _PGT_pae_xen_l2 20
|
|
#define PGT_pae_xen_l2 (1U<<_PGT_pae_xen_l2)
|
|
|
|
/* 16-bit count of uses of this frame as its current type. */
|
|
@@ -141,7 +152,6 @@ extern unsigned long max_page;
|
|
extern unsigned long total_pages;
|
|
void init_frametable(void);
|
|
|
|
-int alloc_page_type(struct page_info *page, unsigned long type);
|
|
void free_page_type(struct page_info *page, unsigned long type);
|
|
int _shadow_mode_refcounts(struct domain *d);
|
|
|
|
Index: 2007-05-14/xen/include/asm-x86/x86_32/page-3level.h
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/include/asm-x86/x86_32/page-3level.h 2007-04-23 10:01:46.000000000 +0200
|
|
+++ 2007-05-14/xen/include/asm-x86/x86_32/page-3level.h 2007-05-14 14:35:02.000000000 +0200
|
|
@@ -85,6 +85,6 @@ typedef l3_pgentry_t root_pgentry_t;
|
|
#define get_pte_flags(x) (((int)((x) >> 32) & ~0xFFF) | ((int)(x) & 0xFFF))
|
|
#define put_pte_flags(x) (((intpte_t)((x) & ~0xFFF) << 32) | ((x) & 0xFFF))
|
|
|
|
-#define L3_DISALLOW_MASK 0xFFFFF1E6U /* must-be-zero */
|
|
+#define L3_DISALLOW_MASK 0xFFFFF1FEU /* must-be-zero */
|
|
|
|
#endif /* __X86_32_PAGE_3LEVEL_H__ */
|
|
Index: 2007-05-14/xen/include/asm-x86/x86_32/page.h
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/include/asm-x86/x86_32/page.h 2007-04-23 10:01:46.000000000 +0200
|
|
+++ 2007-05-14/xen/include/asm-x86/x86_32/page.h 2007-05-14 14:35:02.000000000 +0200
|
|
@@ -29,13 +29,13 @@ extern unsigned int PAGE_HYPERVISOR_NOCA
|
|
(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_GNTTAB)
|
|
|
|
/*
|
|
- * Disallow unused flag bits plus PAT, PSE and GLOBAL.
|
|
+ * Disallow unused flag bits plus PAT/PSE and GLOBAL.
|
|
* Permit the NX bit if the hardware supports it.
|
|
*/
|
|
#define BASE_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX)
|
|
|
|
#define L1_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_GNTTAB)
|
|
-#define L2_DISALLOW_MASK (BASE_DISALLOW_MASK)
|
|
+#define L2_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_PCD | _PAGE_PWT)
|
|
|
|
#endif /* __X86_32_PAGE_H__ */
|
|
|
|
Index: 2007-05-14/xen/include/asm-x86/x86_64/page.h
|
|
===================================================================
|
|
--- 2007-05-14.orig/xen/include/asm-x86/x86_64/page.h 2007-05-03 09:45:09.000000000 +0200
|
|
+++ 2007-05-14/xen/include/asm-x86/x86_64/page.h 2007-05-14 14:35:02.000000000 +0200
|
|
@@ -87,18 +87,18 @@ typedef l4_pgentry_t root_pgentry_t;
|
|
#define _PAGE_NX (cpu_has_nx ? _PAGE_NX_BIT : 0U)
|
|
|
|
/*
|
|
- * Disallow unused flag bits plus PAT, PSE and GLOBAL.
|
|
+ * Disallow unused flag bits plus PAT/PSE and GLOBAL.
|
|
* Permit the NX bit if the hardware supports it.
|
|
* Note that range [62:52] is available for software use on x86/64.
|
|
*/
|
|
#define BASE_DISALLOW_MASK (0xFF800180U & ~_PAGE_NX)
|
|
|
|
#define L1_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_GNTTAB)
|
|
-#define L2_DISALLOW_MASK (BASE_DISALLOW_MASK)
|
|
-#define L3_DISALLOW_MASK (BASE_DISALLOW_MASK)
|
|
-#define L4_DISALLOW_MASK (BASE_DISALLOW_MASK)
|
|
+#define L2_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_PCD | _PAGE_PWT)
|
|
+#define L3_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_PCD | _PAGE_PWT)
|
|
+#define L4_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_PCD | _PAGE_PWT)
|
|
|
|
-#define COMPAT_L3_DISALLOW_MASK 0xFFFFF1E6U
|
|
+#define COMPAT_L3_DISALLOW_MASK 0xFFFFF1FEU
|
|
|
|
#define PAGE_HYPERVISOR (__PAGE_HYPERVISOR | _PAGE_GLOBAL)
|
|
#define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | _PAGE_GLOBAL)
|