aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <andi@firstfloor.org>2008-03-11 22:53:29 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:41:30 -0400
commitc9caa02c529d5e113e40cbc77254558fcdfa4215 (patch)
treecb3f9f5a5d26bf7df542a61bfb524e886d8c6510
parentcc6150321903ca4c3bc9d53b0cdafb05d77d64d0 (diff)
x86: add set_memory_4k to pageattr.c
Add a new function to force split large pages into 4k pages. This is needed for some followup optimizations. I had to add a new field to cpa_data to pass down the information that try_preserve_large_page should not run. Right now no set_page_4k() because I didn't need it and all the specialized users I have in mind would be more comfortable with pure addresses. I also didn't export it because it's unlikely external code needs it. Signed-off-by: Andi Kleen <ak@suse.de> Cc: andreas.herrmann3@amd.com Cc: mingo@elte.hu Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/mm/pageattr.c20
-rw-r--r--include/asm-x86/cacheflush.h1
2 files changed, 17 insertions, 4 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 270cab2e6030..7d9517abc9af 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -31,6 +31,7 @@ struct cpa_data {
31 int numpages; 31 int numpages;
32 int flushtlb; 32 int flushtlb;
33 unsigned long pfn; 33 unsigned long pfn;
34 unsigned force_split : 1;
34}; 35};
35 36
36#ifdef CONFIG_X86_64 37#ifdef CONFIG_X86_64
@@ -262,6 +263,9 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
262 int i, do_split = 1; 263 int i, do_split = 1;
263 unsigned int level; 264 unsigned int level;
264 265
266 if (cpa->force_split)
267 return 1;
268
265 spin_lock_irqsave(&pgd_lock, flags); 269 spin_lock_irqsave(&pgd_lock, flags);
266 /* 270 /*
267 * Check for races, another CPU might have split this page 271 * Check for races, another CPU might have split this page
@@ -696,7 +700,8 @@ static inline int cache_attr(pgprot_t attr)
696} 700}
697 701
698static int change_page_attr_set_clr(unsigned long addr, int numpages, 702static int change_page_attr_set_clr(unsigned long addr, int numpages,
699 pgprot_t mask_set, pgprot_t mask_clr) 703 pgprot_t mask_set, pgprot_t mask_clr,
704 int force_split)
700{ 705{
701 struct cpa_data cpa; 706 struct cpa_data cpa;
702 int ret, cache, checkalias; 707 int ret, cache, checkalias;
@@ -707,7 +712,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
707 */ 712 */
708 mask_set = canon_pgprot(mask_set); 713 mask_set = canon_pgprot(mask_set);
709 mask_clr = canon_pgprot(mask_clr); 714 mask_clr = canon_pgprot(mask_clr);
710 if (!pgprot_val(mask_set) && !pgprot_val(mask_clr)) 715 if (!pgprot_val(mask_set) && !pgprot_val(mask_clr) && !force_split)
711 return 0; 716 return 0;
712 717
713 /* Ensure we are PAGE_SIZE aligned */ 718 /* Ensure we are PAGE_SIZE aligned */
@@ -724,6 +729,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
724 cpa.mask_set = mask_set; 729 cpa.mask_set = mask_set;
725 cpa.mask_clr = mask_clr; 730 cpa.mask_clr = mask_clr;
726 cpa.flushtlb = 0; 731 cpa.flushtlb = 0;
732 cpa.force_split = force_split;
727 733
728 /* No alias checking for _NX bit modifications */ 734 /* No alias checking for _NX bit modifications */
729 checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; 735 checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
@@ -762,13 +768,13 @@ out:
762static inline int change_page_attr_set(unsigned long addr, int numpages, 768static inline int change_page_attr_set(unsigned long addr, int numpages,
763 pgprot_t mask) 769 pgprot_t mask)
764{ 770{
765 return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0)); 771 return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0);
766} 772}
767 773
768static inline int change_page_attr_clear(unsigned long addr, int numpages, 774static inline int change_page_attr_clear(unsigned long addr, int numpages,
769 pgprot_t mask) 775 pgprot_t mask)
770{ 776{
771 return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask); 777 return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0);
772} 778}
773 779
774int _set_memory_uc(unsigned long addr, int numpages) 780int _set_memory_uc(unsigned long addr, int numpages)
@@ -847,6 +853,12 @@ int set_memory_np(unsigned long addr, int numpages)
847 return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT)); 853 return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
848} 854}
849 855
856int set_memory_4k(unsigned long addr, int numpages)
857{
858 return change_page_attr_set_clr(addr, numpages, __pgprot(0),
859 __pgprot(0), 1);
860}
861
850int set_pages_uc(struct page *page, int numpages) 862int set_pages_uc(struct page *page, int numpages)
851{ 863{
852 unsigned long addr = (unsigned long)page_address(page); 864 unsigned long addr = (unsigned long)page_address(page);
diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h
index 7ab5b520b7bd..cb1d6f8fd003 100644
--- a/include/asm-x86/cacheflush.h
+++ b/include/asm-x86/cacheflush.h
@@ -45,6 +45,7 @@ int set_memory_nx(unsigned long addr, int numpages);
45int set_memory_ro(unsigned long addr, int numpages); 45int set_memory_ro(unsigned long addr, int numpages);
46int set_memory_rw(unsigned long addr, int numpages); 46int set_memory_rw(unsigned long addr, int numpages);
47int set_memory_np(unsigned long addr, int numpages); 47int set_memory_np(unsigned long addr, int numpages);
48int set_memory_4k(unsigned long addr, int numpages);
48 49
49void clflush_cache_range(void *addr, unsigned int size); 50void clflush_cache_range(void *addr, unsigned int size);
50 51