[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC 3/4] Add xen superpage splitting support to arm
Updates xen_pt_update_entry function from xen/arch/arm/mm.c to automatically split superpages as needed. --- xen/arch/arm/mm.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 6301752..91b9c2b 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -753,8 +753,78 @@ static int create_xen_table(lpae_t *entry) } #define XEN_TABLE_MAP_FAILED 0 -#define XEN_TABLE_SUPER_PAGE 1 -#define XEN_TABLE_NORMAL_PAGE 2 +#define XEN_TABLE_NORMAL_PAGE 1 + +/* More or less taken from p2m_split_superpage, without the p2m stuff */ +static bool xen_split_superpage(lpae_t *entry, unsigned int level, + unsigned int target, const unsigned int *offsets) +{ + struct page_info *page; + lpae_t pte, *table; + unsigned int i; + bool rv = true; + + mfn_t mfn = lpae_get_mfn(*entry); + unsigned int next_level = level + 1; + unsigned int level_order = XEN_PT_LEVEL_ORDER(next_level); + + ASSERT(level < target); + ASSERT(lpae_is_superpage(*entry, level)); + + page = alloc_domheap_page(NULL, 0); + if ( !page ) + return false; + + table = __map_domain_page(page); + + /* + * We are either splitting a first level 1G page into 512 second level + * 2M pages, or a second level 2M page into 512 third level 4K pages. + */ + for ( i = 0; i < XEN_PT_LPAE_ENTRIES; i++ ) + { + lpae_t *new_entry = table + i; + + /* + * Use the content of the superpage entry and override + * the necessary fields. So the correct permission are kept. + */ + pte = *entry; + lpae_set_mfn(pte, mfn_add(mfn, i << level_order)); + + /* + * First and second level pages set walk.table = 0, but third + * level entries set walk.table = 1. + */ + pte.walk.table = (next_level == 3); + + write_pte(new_entry, pte); + } + + /* + * Shatter superpage in the page to the level we want to make the + * changes. + * This is done outside the loop to avoid checking the offset to + * know whether the entry should be shattered for every entry. + */ + if ( next_level != target ) + rv = xen_split_superpage(table + offsets[next_level], + level + 1, target, offsets); + + clean_dcache_va_range(table, PAGE_SIZE); + unmap_domain_page(table); + + /* + * Generate the entry for this new table we created, + * and write it back in place of the superpage entry. + */ + pte = mfn_to_xen_entry(page_to_mfn(page), MT_NORMAL); + pte.pt.table = 1; + write_pte(entry, pte); + clean_dcache(*entry); + + return rv; +} /* * Take the currently mapped table, find the corresponding entry, @@ -767,16 +837,15 @@ static int create_xen_table(lpae_t *entry) * XEN_TABLE_MAP_FAILED: Either read_only was set and the entry * was empty, or allocating a new page failed. * XEN_TABLE_NORMAL_PAGE: next level mapped normally - * XEN_TABLE_SUPER_PAGE: The next entry points to a superpage. */ static int xen_pt_next_level(bool read_only, unsigned int level, - lpae_t **table, unsigned int offset) + lpae_t **table, const unsigned int *offsets) { lpae_t *entry; int ret; mfn_t mfn; - entry = *table + offset; + entry = *table + offsets[level]; if ( !lpae_is_valid(*entry) ) { @@ -790,7 +859,8 @@ static int xen_pt_next_level(bool read_only, unsigned int level, /* The function xen_pt_next_level is never called at the 3rd level */ if ( lpae_is_mapping(*entry, level) ) - return XEN_TABLE_SUPER_PAGE; + /* Shatter the superpage before continuing */ + xen_split_superpage(entry, level, level + 1, offsets); mfn = lpae_get_mfn(*entry); @@ -915,7 +985,7 @@ static int xen_pt_update_entry(mfn_t root, unsigned long virt, table = xen_map_table(root); for ( level = HYP_PT_ROOT_LEVEL; level < target; level++ ) { - rc = xen_pt_next_level(read_only, level, &table, offsets[level]); + rc = xen_pt_next_level(read_only, level, &table, offsets); if ( rc == XEN_TABLE_MAP_FAILED ) { /* @@ -941,12 +1011,7 @@ static int xen_pt_update_entry(mfn_t root, unsigned long virt, break; } - if ( level != target ) - { - mm_printk("%s: Shattering superpage is not supported\n", __func__); - rc = -EOPNOTSUPP; - goto out; - } + BUG_ON( level != target ); entry = table + offsets[level]; -- 2.7.4
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |