Re: [PATCH v6 03/11] mm, x86: Add support for eXclusive Page Frame Ownership (XPFO)

From: Dave Hansen
Date: Wed Sep 20 2017 - 19:46:51 EST


On 09/12/2017 11:13 AM, Tycho Andersen wrote:
> -void xpfo_alloc_pages(struct page *page, int order, gfp_t gfp)
> +void xpfo_alloc_pages(struct page *page, int order, gfp_t gfp, bool will_map)
> {
> int i, flush_tlb = 0;
> struct xpfo *xpfo;
> @@ -116,8 +116,14 @@ void xpfo_alloc_pages(struct page *page, int order, gfp_t gfp)
> * Tag the page as a user page and flush the TLB if it
> * was previously allocated to the kernel.
> */
> - if (!test_and_set_bit(XPFO_PAGE_USER, &xpfo->flags))
> + bool was_user = !test_and_set_bit(XPFO_PAGE_USER,
> + &xpfo->flags);
> +
> + if (was_user || !will_map) {
> + set_kpte(page_address(page + i), page + i,
> + __pgprot(0));
> flush_tlb = 1;
> + }

Shouldn't the "was_user" be "was_kernel"?

Also, the way this now works, let's say we have a nice, 2MB pmd_t (page
table entry) mapping a nice, 2MB page in the allocator. Then it gets
allocated to userspace. We do

for (i = 0; i < (1 << order); i++) {
...
set_kpte(page_address(page + i), page+i, __pgprot(0));
}

The set_kpte() will take the nice, 2MB mapping and break it down into
512 4k mappings, all pointing to a non-present PTE, in a newly-allocated
PTE page. So, you get the same result and waste 4k of memory in the
process, *AND* make it slower because we added a level to the page tables.

I think you actually want to make a single set_kpte() call at the end of
the function. That's faster and preserves the large page in the direct
mapping.