From 2705e3fc47bd2a6009cca7f5c985239f8130a258 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 22 Mar 2006 00:08:33 -0800 Subject: [PATCH] --- yaml --- r: 22471 b: refs/heads/master c: 4fa4f53bf92139595cae6f1a3d972fc0a3451d29 h: refs/heads/master i: 22469: 554cfca53d6707fc71f4ddd367860af252d76ca5 22467: 133d66962e99b1f2f1e0f4bd0b47a2d5083cdba4 22463: e2472809f05790c6246473742d3cb38c12996b3f v: v3 --- [refs] | 2 +- trunk/arch/x86_64/mm/pageattr.c | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/[refs] b/[refs] index d335b037c5d0..76b41690d2c2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 20aaffd6a6492a5f7975dd7be967cdf0e4d978c4 +refs/heads/master: 4fa4f53bf92139595cae6f1a3d972fc0a3451d29 diff --git a/trunk/arch/x86_64/mm/pageattr.c b/trunk/arch/x86_64/mm/pageattr.c index efe5af14c7db..531ad21447b1 100644 --- a/trunk/arch/x86_64/mm/pageattr.c +++ b/trunk/arch/x86_64/mm/pageattr.c @@ -45,6 +45,13 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot, pte_t *pbase; if (!base) return NULL; + /* + * page_private is used to track the number of entries in + * the page table page have non standard attributes. + */ + SetPagePrivate(base); + page_private(base) = 0; + address = __pa(address); addr = address & LARGE_PAGE_MASK; pbase = (pte_t *)page_address(base); @@ -124,8 +131,8 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, set_pte(kpte, pfn_pte(pfn, prot)); } else { /* - * split_large_page will take the reference for this change_page_attr - * on the split page. + * split_large_page will take the reference for this + * change_page_attr on the split page. */ struct page *split; @@ -137,23 +144,20 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, set_pte(kpte,mk_pte(split, ref_prot2)); kpte_page = split; } - get_page(kpte_page); + page_private(kpte_page)++; } else if ((kpte_flags & _PAGE_PSE) == 0) { set_pte(kpte, pfn_pte(pfn, ref_prot)); - __put_page(kpte_page); + BUG_ON(page_private(kpte_page) == 0); + page_private(kpte_page)--; } else BUG(); /* on x86-64 the direct mapping set at boot is not using 4k pages */ BUG_ON(PageReserved(kpte_page)); - switch (page_count(kpte_page)) { - case 1: + if (page_private(kpte_page) == 0) { save_page(kpte_page); revert_page(address, ref_prot); - break; - case 0: - BUG(); /* memleak and failed 2M page regeneration */ } return 0; } @@ -216,6 +220,7 @@ void global_flush_tlb(void) while (dpage) { struct page *tmp = dpage; dpage = (struct page *)dpage->lru.next; + ClearPagePrivate(tmp); __free_page(tmp); } }