#define PAGE_CACHE_ATTRS (_PAGE_PAT|_PAGE_PCD|_PAGE_PWT)
-bool __read_mostly opt_allow_superpage;
-boolean_param("allowsuperpage", opt_allow_superpage);
-
-static void put_superpage(unsigned long mfn);
-
static uint32_t base_disallow_mask;
/* Global bit is allowed to be set on L1 PTEs. Intended for user mappings. */
#define L1_DISALLOW_MASK ((base_disallow_mask | _PAGE_GNTTAB) & ~_PAGE_GLOBAL)
-#define L2_DISALLOW_MASK (unlikely(opt_allow_superpage) \
- ? base_disallow_mask & ~_PAGE_PSE \
- : base_disallow_mask)
+#define L2_DISALLOW_MASK base_disallow_mask
#define l3_disallow_mask(d) (!is_pv_32bit_domain(d) ? \
base_disallow_mask : 0xFFFFF198U)
memset(end, -1, s - e);
}
-static void __init init_spagetable(void)
-{
- BUILD_BUG_ON(XEN_VIRT_END > SPAGETABLE_VIRT_START);
-
- init_frametable_chunk(spage_table,
- mem_hotplug ? spage_table + SPAGETABLE_NR
- : pdx_to_spage(max_pdx - 1) + 1);
-}
-
void __init init_frametable(void)
{
unsigned int sidx, eidx, nidx;
: end_pg;
init_frametable_chunk(pdx_to_page(sidx * PDX_GROUP_COUNT), top_pg);
memset(end_pg, -1, (unsigned long)top_pg - (unsigned long)end_pg);
-
- if (opt_allow_superpage)
- init_spagetable();
}
#ifndef NDEBUG
return rc;
}
- if ( !opt_allow_superpage )
- {
- gdprintk(XENLOG_WARNING, "PV superpages disabled in hypervisor\n");
- return -EINVAL;
- }
-
- if ( mfn & (L1_PAGETABLE_ENTRIES - 1) )
- {
- gdprintk(XENLOG_WARNING,
- "Unaligned superpage map attempt mfn %" PRI_mfn "\n", mfn);
- return -EINVAL;
- }
-
- return get_superpage(mfn, d);
+ return -EINVAL;
}
return 1;
if ( l2e_get_flags(l2e) & _PAGE_PSE )
- put_superpage(l2e_get_pfn(l2e));
- else
+ {
+ struct page_info *page = mfn_to_page(l2e_get_pfn(l2e));
+ unsigned int i;
+
+ for ( i = 0; i < (1u << PAGETABLE_ORDER); i++, page++ )
+ put_page_and_type(page);
+ } else
put_page_and_type(l2e_get_page(l2e));
return 0;
return __get_page_type(page, type, 1);
}
-static int get_spage_pages(struct page_info *page, struct domain *d)
-{
- unsigned int i;
-
- for ( i = 0; i < (1u << PAGETABLE_ORDER); i++, page++ )
- {
- if ( !get_page_and_type(page, d, PGT_writable_page) )
- {
- while ( i-- > 0 )
- put_page_and_type(--page);
- return 0;
- }
- }
- return 1;
-}
-
-static void put_spage_pages(struct page_info *page)
-{
- unsigned int i;
-
- for ( i = 0; i < (1u << PAGETABLE_ORDER); i++, page++ )
- put_page_and_type(page);
-}
-
-static int mark_superpage(struct spage_info *spage, struct domain *d)
-{
- unsigned long x, nx, y = spage->type_info;
- int pages_done = 0;
-
- ASSERT(opt_allow_superpage);
-
- do {
- x = y;
- nx = x + 1;
- if ( (x & SGT_type_mask) == SGT_mark )
- {
- gdprintk(XENLOG_WARNING,
- "Duplicate superpage mark attempt mfn %" PRI_mfn "\n",
- spage_to_mfn(spage));
- if ( pages_done )
- put_spage_pages(spage_to_page(spage));
- return -EINVAL;
- }
- if ( (x & SGT_type_mask) == SGT_dynamic )
- {
- if ( pages_done )
- {
- put_spage_pages(spage_to_page(spage));
- pages_done = 0;
- }
- }
- else if ( !pages_done )
- {
- if ( !get_spage_pages(spage_to_page(spage), d) )
- {
- gdprintk(XENLOG_WARNING,
- "Superpage type conflict in mark attempt mfn %" PRI_mfn "\n",
- spage_to_mfn(spage));
- return -EINVAL;
- }
- pages_done = 1;
- }
- nx = (nx & ~SGT_type_mask) | SGT_mark;
-
- } while ( (y = cmpxchg(&spage->type_info, x, nx)) != x );
-
- return 0;
-}
-
-static int unmark_superpage(struct spage_info *spage)
-{
- unsigned long x, nx, y = spage->type_info;
- unsigned long do_pages = 0;
-
- ASSERT(opt_allow_superpage);
-
- do {
- x = y;
- nx = x - 1;
- if ( (x & SGT_type_mask) != SGT_mark )
- {
- gdprintk(XENLOG_WARNING,
- "Attempt to unmark unmarked superpage mfn %" PRI_mfn "\n",
- spage_to_mfn(spage));
- return -EINVAL;
- }
- if ( (nx & SGT_count_mask) == 0 )
- {
- nx = (nx & ~SGT_type_mask) | SGT_none;
- do_pages = 1;
- }
- else
- {
- nx = (nx & ~SGT_type_mask) | SGT_dynamic;
- }
- } while ( (y = cmpxchg(&spage->type_info, x, nx)) != x );
-
- if ( do_pages )
- put_spage_pages(spage_to_page(spage));
-
- return 0;
-}
-
-void clear_superpage_mark(struct page_info *page)
-{
- struct spage_info *spage;
-
- if ( !opt_allow_superpage )
- return;
-
- spage = page_to_spage(page);
- if ((spage->type_info & SGT_type_mask) == SGT_mark)
- unmark_superpage(spage);
-
-}
-
-int get_superpage(unsigned long mfn, struct domain *d)
-{
- struct spage_info *spage;
- unsigned long x, nx, y;
- int pages_done = 0;
-
- ASSERT(opt_allow_superpage);
-
- if ( !mfn_valid(_mfn(mfn | (L1_PAGETABLE_ENTRIES - 1))) )
- return -EINVAL;
-
- spage = mfn_to_spage(mfn);
- y = spage->type_info;
- do {
- x = y;
- nx = x + 1;
- if ( (x & SGT_type_mask) != SGT_none )
- {
- if ( pages_done )
- {
- put_spage_pages(spage_to_page(spage));
- pages_done = 0;
- }
- }
- else
- {
- if ( !get_spage_pages(spage_to_page(spage), d) )
- {
- gdprintk(XENLOG_WARNING,
- "Type conflict on superpage mapping mfn %" PRI_mfn "\n",
- spage_to_mfn(spage));
- return -EINVAL;
- }
- pages_done = 1;
- nx = (nx & ~SGT_type_mask) | SGT_dynamic;
- }
- } while ( (y = cmpxchg(&spage->type_info, x, nx)) != x );
-
- return 0;
-}
-
-static void put_superpage(unsigned long mfn)
-{
- struct spage_info *spage;
- unsigned long x, nx, y;
- unsigned long do_pages = 0;
-
- if ( !opt_allow_superpage )
- {
- put_spage_pages(mfn_to_page(mfn));
- return;
- }
-
- spage = mfn_to_spage(mfn);
- y = spage->type_info;
- do {
- x = y;
- nx = x - 1;
- if ((x & SGT_type_mask) == SGT_dynamic)
- {
- if ((nx & SGT_count_mask) == 0)
- {
- nx = (nx & ~SGT_type_mask) | SGT_none;
- do_pages = 1;
- }
- }
-
- } while ((y = cmpxchg(&spage->type_info, x, nx)) != x);
-
- if (do_pages)
- put_spage_pages(spage_to_page(spage));
-
- return;
-}
-
int put_old_guest_table(struct vcpu *v)
{
int rc;
case MMUEXT_MARK_SUPER:
case MMUEXT_UNMARK_SUPER:
- {
- unsigned long mfn = op.arg1.mfn;
-
- if ( !opt_allow_superpage )
- rc = -EOPNOTSUPP;
- else if ( unlikely(currd != pg_owner) )
- rc = -EPERM;
- else if ( mfn & (L1_PAGETABLE_ENTRIES - 1) )
- {
- gdprintk(XENLOG_WARNING,
- "Unaligned superpage mfn %" PRI_mfn "\n", mfn);
- rc = -EINVAL;
- }
- else if ( !mfn_valid(_mfn(mfn | (L1_PAGETABLE_ENTRIES - 1))) )
- rc = -EINVAL;
- else if ( op.cmd == MMUEXT_MARK_SUPER )
- rc = mark_superpage(mfn_to_spage(mfn), currd);
- else
- rc = unmark_superpage(mfn_to_spage(mfn));
+ rc = -EOPNOTSUPP;
break;
- }
default:
rc = -ENOSYS;
* 0xffff82d080000000 - 0xffff82d0bfffffff [1GB, 2^30 bytes, PML4:261]
* Xen text, static data, bss.
#ifndef CONFIG_BIGMEM
- * 0xffff82d0c0000000 - 0xffff82dffbffffff [61GB - 64MB, PML4:261]
+ * 0xffff82d0c0000000 - 0xffff82dfffffffff [61GB, PML4:261]
* Reserved for future use.
- * 0xffff82dffc000000 - 0xffff82dfffffffff [64MB, 2^26 bytes, PML4:261]
- * Super-page information array.
* 0xffff82e000000000 - 0xffff82ffffffffff [128GB, 2^37 bytes, PML4:261]
* Page-frame information array.
* 0xffff830000000000 - 0xffff87ffffffffff [5TB, 5*2^40 bytes, PML4:262-271]
* 1:1 direct mapping of all physical memory.
#else
- * 0xffff82d0c0000000 - 0xffff82ffdfffffff [188.5GB, PML4:261]
+ * 0xffff82d0c0000000 - 0xffff82ffffffffff [189GB, PML4:261]
* Reserved for future use.
- * 0xffff82ffe0000000 - 0xffff82ffffffffff [512MB, 2^29 bytes, PML4:261]
- * Super-page information array.
* 0xffff830000000000 - 0xffff847fffffffff [1.5TB, 3*2^39 bytes, PML4:262-264]
* Page-frame information array.
* 0xffff848000000000 - 0xffff87ffffffffff [3.5TB, 7*2^39 bytes, PML4:265-271]
#define XEN_VIRT_START (HIRO_COMPAT_MPT_VIRT_END)
#define XEN_VIRT_END (XEN_VIRT_START + GB(1))
-/* Slot 261: superpage information array (64MB or 512MB). */
-#define SPAGETABLE_VIRT_END FRAMETABLE_VIRT_START
-#define SPAGETABLE_NR (((FRAMETABLE_NR - 1) >> (SUPERPAGE_SHIFT - \
- PAGE_SHIFT)) + 1)
-#define SPAGETABLE_SIZE (SPAGETABLE_NR * sizeof(struct spage_info))
-#define SPAGETABLE_VIRT_START ((SPAGETABLE_VIRT_END - SPAGETABLE_SIZE) & \
- (_AC(-1,UL) << SUPERPAGE_SHIFT))
-
#ifndef CONFIG_BIGMEM
/* Slot 261: page-frame information array (128GB). */
#define FRAMETABLE_SIZE GB(128)
#define PGC_count_width PG_shift(9)
#define PGC_count_mask ((1UL<<PGC_count_width)-1)
-struct spage_info
-{
- unsigned long type_info;
-};
-
- /* The following page types are MUTUALLY EXCLUSIVE. */
-#define SGT_none PG_mask(0, 2) /* superpage not in use */
-#define SGT_mark PG_mask(1, 2) /* Marked as a superpage */
-#define SGT_dynamic PG_mask(2, 2) /* has been dynamically mapped as a superpage */
-#define SGT_type_mask PG_mask(3, 2) /* Bits 30-31 or 62-63. */
-
- /* Count of uses of this superpage as its current type. */
-#define SGT_count_width PG_shift(3)
-#define SGT_count_mask ((1UL<<SGT_count_width)-1)
-
#define is_xen_heap_page(page) ((page)->count_info & PGC_xen_heap)
#define is_xen_heap_mfn(mfn) \
(__mfn_valid(mfn) && is_xen_heap_page(__mfn_to_page(mfn)))
extern void free_shared_domheap_page(struct page_info *page);
#define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
-#define spage_table ((struct spage_info *)SPAGETABLE_VIRT_START)
-int get_superpage(unsigned long mfn, struct domain *d);
extern unsigned long max_page;
extern unsigned long total_pages;
void init_frametable(void);
bool is_iomem_page(mfn_t mfn);
-void clear_superpage_mark(struct page_info *page);
-
const unsigned long *get_platform_badpages(unsigned int *array_size);
/* Per page locks:
* page_lock() is used for two purposes: pte serialization, and memory sharing.
int check_descriptor(const struct domain *, struct desc_struct *d);
-extern bool opt_allow_superpage;
extern paddr_t mem_hotplug;
/******************************************************************************