diff options
author | Andi Kleen <andi@firstfloor.org> | 2008-03-11 22:53:29 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-17 11:41:30 -0400 |
commit | c9caa02c529d5e113e40cbc77254558fcdfa4215 (patch) | |
tree | cb3f9f5a5d26bf7df542a61bfb524e886d8c6510 | |
parent | cc6150321903ca4c3bc9d53b0cdafb05d77d64d0 (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.c | 20 | ||||
-rw-r--r-- | include/asm-x86/cacheflush.h | 1 |
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 | ||
698 | static int change_page_attr_set_clr(unsigned long addr, int numpages, | 702 | static 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: | |||
762 | static inline int change_page_attr_set(unsigned long addr, int numpages, | 768 | static 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 | ||
768 | static inline int change_page_attr_clear(unsigned long addr, int numpages, | 774 | static 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 | ||
774 | int _set_memory_uc(unsigned long addr, int numpages) | 780 | int _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 | ||
856 | int 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 | |||
850 | int set_pages_uc(struct page *page, int numpages) | 862 | int 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); | |||
45 | int set_memory_ro(unsigned long addr, int numpages); | 45 | int set_memory_ro(unsigned long addr, int numpages); |
46 | int set_memory_rw(unsigned long addr, int numpages); | 46 | int set_memory_rw(unsigned long addr, int numpages); |
47 | int set_memory_np(unsigned long addr, int numpages); | 47 | int set_memory_np(unsigned long addr, int numpages); |
48 | int set_memory_4k(unsigned long addr, int numpages); | ||
48 | 49 | ||
49 | void clflush_cache_range(void *addr, unsigned int size); | 50 | void clflush_cache_range(void *addr, unsigned int size); |
50 | 51 | ||