diff options
author | Shaohua Li <shaohua.li@intel.com> | 2008-08-20 22:46:06 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-21 07:47:45 -0400 |
commit | d75586ad01e6c5a30e7337fb87d61e03556a1ecb (patch) | |
tree | 71fa07acb4b408e51a72b2c0630c2a620196caf4 | |
parent | cacf890694a36124ceddce44ff4c7b02d372ce7c (diff) |
x86, pageattr: introduce APIs to change pageattr of a page array
Add array interface APIs of pageattr. page based cache flush is quite
slow for a lot of pages. If pages are more than 1024 (4M), the patch
will use a wbinvd(). We have a simple test here (run a 3d game - open
arena), nearly all agp memory allocation are small (< 1M), so suppose
this will not impact runtime performance.
Signed-off-by: Dave Airlie <airlied@gmail.com>
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/mm/pageattr.c | 216 | ||||
-rw-r--r-- | include/asm-x86/cacheflush.h | 3 |
2 files changed, 169 insertions, 50 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 5c06469a065..041e81ef673 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -25,15 +25,19 @@ | |||
25 | * The current flushing context - we pass it instead of 5 arguments: | 25 | * The current flushing context - we pass it instead of 5 arguments: |
26 | */ | 26 | */ |
27 | struct cpa_data { | 27 | struct cpa_data { |
28 | unsigned long vaddr; | 28 | unsigned long *vaddr; |
29 | pgprot_t mask_set; | 29 | pgprot_t mask_set; |
30 | pgprot_t mask_clr; | 30 | pgprot_t mask_clr; |
31 | int numpages; | 31 | int numpages; |
32 | int flushtlb; | 32 | int flags; |
33 | unsigned long pfn; | 33 | unsigned long pfn; |
34 | unsigned force_split : 1; | 34 | unsigned force_split : 1; |
35 | int curpage; | ||
35 | }; | 36 | }; |
36 | 37 | ||
38 | #define CPA_FLUSHTLB 1 | ||
39 | #define CPA_ARRAY 2 | ||
40 | |||
37 | #ifdef CONFIG_PROC_FS | 41 | #ifdef CONFIG_PROC_FS |
38 | static unsigned long direct_pages_count[PG_LEVEL_NUM]; | 42 | static unsigned long direct_pages_count[PG_LEVEL_NUM]; |
39 | 43 | ||
@@ -184,6 +188,41 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache) | |||
184 | } | 188 | } |
185 | } | 189 | } |
186 | 190 | ||
191 | static void cpa_flush_array(unsigned long *start, int numpages, int cache) | ||
192 | { | ||
193 | unsigned int i, level; | ||
194 | unsigned long *addr; | ||
195 | |||
196 | BUG_ON(irqs_disabled()); | ||
197 | |||
198 | on_each_cpu(__cpa_flush_range, NULL, 1); | ||
199 | |||
200 | if (!cache) | ||
201 | return; | ||
202 | |||
203 | /* 4M threshold */ | ||
204 | if (numpages >= 1024) { | ||
205 | if (boot_cpu_data.x86_model >= 4) | ||
206 | wbinvd(); | ||
207 | return; | ||
208 | } | ||
209 | /* | ||
210 | * We only need to flush on one CPU, | ||
211 | * clflush is a MESI-coherent instruction that | ||
212 | * will cause all other CPUs to flush the same | ||
213 | * cachelines: | ||
214 | */ | ||
215 | for (i = 0, addr = start; i < numpages; i++, addr++) { | ||
216 | pte_t *pte = lookup_address(*addr, &level); | ||
217 | |||
218 | /* | ||
219 | * Only flush present addresses: | ||
220 | */ | ||
221 | if (pte && (pte_val(*pte) & _PAGE_PRESENT)) | ||
222 | clflush_cache_range((void *) *addr, PAGE_SIZE); | ||
223 | } | ||
224 | } | ||
225 | |||
187 | /* | 226 | /* |
188 | * Certain areas of memory on x86 require very specific protection flags, | 227 | * Certain areas of memory on x86 require very specific protection flags, |
189 | * for example the BIOS area or kernel text. Callers don't always get this | 228 | * for example the BIOS area or kernel text. Callers don't always get this |
@@ -392,7 +431,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
392 | */ | 431 | */ |
393 | new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot)); | 432 | new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot)); |
394 | __set_pmd_pte(kpte, address, new_pte); | 433 | __set_pmd_pte(kpte, address, new_pte); |
395 | cpa->flushtlb = 1; | 434 | cpa->flags |= CPA_FLUSHTLB; |
396 | do_split = 0; | 435 | do_split = 0; |
397 | } | 436 | } |
398 | 437 | ||
@@ -578,11 +617,16 @@ out_unlock: | |||
578 | 617 | ||
579 | static int __change_page_attr(struct cpa_data *cpa, int primary) | 618 | static int __change_page_attr(struct cpa_data *cpa, int primary) |
580 | { | 619 | { |
581 | unsigned long address = cpa->vaddr; | 620 | unsigned long address; |
582 | int do_split, err; | 621 | int do_split, err; |
583 | unsigned int level; | 622 | unsigned int level; |
584 | pte_t *kpte, old_pte; | 623 | pte_t *kpte, old_pte; |
585 | 624 | ||
625 | if (cpa->flags & CPA_ARRAY) | ||
626 | address = cpa->vaddr[cpa->curpage]; | ||
627 | else | ||
628 | address = *cpa->vaddr; | ||
629 | |||
586 | repeat: | 630 | repeat: |
587 | kpte = lookup_address(address, &level); | 631 | kpte = lookup_address(address, &level); |
588 | if (!kpte) | 632 | if (!kpte) |
@@ -594,8 +638,8 @@ repeat: | |||
594 | return 0; | 638 | return 0; |
595 | printk(KERN_WARNING "CPA: called for zero pte. " | 639 | printk(KERN_WARNING "CPA: called for zero pte. " |
596 | "vaddr = %lx cpa->vaddr = %lx\n", address, | 640 | "vaddr = %lx cpa->vaddr = %lx\n", address, |
597 | cpa->vaddr); | ||
598 | WARN_ON(1); | 641 | WARN_ON(1); |
642 | *cpa->vaddr); | ||
599 | return -EINVAL; | 643 | return -EINVAL; |
600 | } | 644 | } |
601 | 645 | ||
@@ -621,7 +665,7 @@ repeat: | |||
621 | */ | 665 | */ |
622 | if (pte_val(old_pte) != pte_val(new_pte)) { | 666 | if (pte_val(old_pte) != pte_val(new_pte)) { |
623 | set_pte_atomic(kpte, new_pte); | 667 | set_pte_atomic(kpte, new_pte); |
624 | cpa->flushtlb = 1; | 668 | cpa->flags |= CPA_FLUSHTLB; |
625 | } | 669 | } |
626 | cpa->numpages = 1; | 670 | cpa->numpages = 1; |
627 | return 0; | 671 | return 0; |
@@ -645,7 +689,7 @@ repeat: | |||
645 | */ | 689 | */ |
646 | err = split_large_page(kpte, address); | 690 | err = split_large_page(kpte, address); |
647 | if (!err) { | 691 | if (!err) { |
648 | cpa->flushtlb = 1; | 692 | cpa->flags |= CPA_FLUSHTLB; |
649 | goto repeat; | 693 | goto repeat; |
650 | } | 694 | } |
651 | 695 | ||
@@ -658,6 +702,7 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
658 | { | 702 | { |
659 | struct cpa_data alias_cpa; | 703 | struct cpa_data alias_cpa; |
660 | int ret = 0; | 704 | int ret = 0; |
705 | unsigned long temp_cpa_vaddr, vaddr; | ||
661 | 706 | ||
662 | if (cpa->pfn >= max_pfn_mapped) | 707 | if (cpa->pfn >= max_pfn_mapped) |
663 | return 0; | 708 | return 0; |
@@ -670,16 +715,24 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
670 | * No need to redo, when the primary call touched the direct | 715 | * No need to redo, when the primary call touched the direct |
671 | * mapping already: | 716 | * mapping already: |
672 | */ | 717 | */ |
673 | if (!(within(cpa->vaddr, PAGE_OFFSET, | 718 | if (cpa->flags & CPA_ARRAY) |
719 | vaddr = cpa->vaddr[cpa->curpage]; | ||
720 | else | ||
721 | vaddr = *cpa->vaddr; | ||
722 | |||
723 | if (!(within(vaddr, PAGE_OFFSET, | ||
674 | PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT)) | 724 | PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT)) |
675 | #ifdef CONFIG_X86_64 | 725 | #ifdef CONFIG_X86_64 |
676 | || within(cpa->vaddr, PAGE_OFFSET + (1UL<<32), | 726 | || within(vaddr, PAGE_OFFSET + (1UL<<32), |
677 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)) | 727 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)) |
678 | #endif | 728 | #endif |
679 | )) { | 729 | )) { |
680 | 730 | ||
681 | alias_cpa = *cpa; | 731 | alias_cpa = *cpa; |
682 | alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); | 732 | temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); |
733 | alias_cpa.vaddr = &temp_cpa_vaddr; | ||
734 | alias_cpa.flags &= ~CPA_ARRAY; | ||
735 | |||
683 | 736 | ||
684 | ret = __change_page_attr_set_clr(&alias_cpa, 0); | 737 | ret = __change_page_attr_set_clr(&alias_cpa, 0); |
685 | } | 738 | } |
@@ -691,7 +744,7 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
691 | * No need to redo, when the primary call touched the high | 744 | * No need to redo, when the primary call touched the high |
692 | * mapping already: | 745 | * mapping already: |
693 | */ | 746 | */ |
694 | if (within(cpa->vaddr, (unsigned long) _text, (unsigned long) _end)) | 747 | if (within(vaddr, (unsigned long) _text, (unsigned long) _end)) |
695 | return 0; | 748 | return 0; |
696 | 749 | ||
697 | /* | 750 | /* |
@@ -702,8 +755,9 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
702 | return 0; | 755 | return 0; |
703 | 756 | ||
704 | alias_cpa = *cpa; | 757 | alias_cpa = *cpa; |
705 | alias_cpa.vaddr = | 758 | temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; |
706 | (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; | 759 | alias_cpa.vaddr = &temp_cpa_vaddr; |
760 | alias_cpa.flags &= ~CPA_ARRAY; | ||
707 | 761 | ||
708 | /* | 762 | /* |
709 | * The high mapping range is imprecise, so ignore the return value. | 763 | * The high mapping range is imprecise, so ignore the return value. |
@@ -723,6 +777,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | |||
723 | * preservation check. | 777 | * preservation check. |
724 | */ | 778 | */ |
725 | cpa->numpages = numpages; | 779 | cpa->numpages = numpages; |
780 | /* for array changes, we can't use large page */ | ||
781 | if (cpa->flags & CPA_ARRAY) | ||
782 | cpa->numpages = 1; | ||
726 | 783 | ||
727 | ret = __change_page_attr(cpa, checkalias); | 784 | ret = __change_page_attr(cpa, checkalias); |
728 | if (ret) | 785 | if (ret) |
@@ -741,7 +798,11 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | |||
741 | */ | 798 | */ |
742 | BUG_ON(cpa->numpages > numpages); | 799 | BUG_ON(cpa->numpages > numpages); |
743 | numpages -= cpa->numpages; | 800 | numpages -= cpa->numpages; |
744 | cpa->vaddr += cpa->numpages * PAGE_SIZE; | 801 | if (cpa->flags & CPA_ARRAY) |
802 | cpa->curpage++; | ||
803 | else | ||
804 | *cpa->vaddr += cpa->numpages * PAGE_SIZE; | ||
805 | |||
745 | } | 806 | } |
746 | return 0; | 807 | return 0; |
747 | } | 808 | } |
@@ -752,9 +813,9 @@ static inline int cache_attr(pgprot_t attr) | |||
752 | (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); | 813 | (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); |
753 | } | 814 | } |
754 | 815 | ||
755 | static int change_page_attr_set_clr(unsigned long addr, int numpages, | 816 | static int change_page_attr_set_clr(unsigned long *addr, int numpages, |
756 | pgprot_t mask_set, pgprot_t mask_clr, | 817 | pgprot_t mask_set, pgprot_t mask_clr, |
757 | int force_split) | 818 | int force_split, int array) |
758 | { | 819 | { |
759 | struct cpa_data cpa; | 820 | struct cpa_data cpa; |
760 | int ret, cache, checkalias; | 821 | int ret, cache, checkalias; |
@@ -769,12 +830,22 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
769 | return 0; | 830 | return 0; |
770 | 831 | ||
771 | /* Ensure we are PAGE_SIZE aligned */ | 832 | /* Ensure we are PAGE_SIZE aligned */ |
772 | if (addr & ~PAGE_MASK) { | 833 | if (!array) { |
773 | addr &= PAGE_MASK; | 834 | if (*addr & ~PAGE_MASK) { |
774 | /* | 835 | *addr &= PAGE_MASK; |
775 | * People should not be passing in unaligned addresses: | 836 | /* |
776 | */ | 837 | * People should not be passing in unaligned addresses: |
777 | WARN_ON_ONCE(1); | 838 | */ |
839 | WARN_ON_ONCE(1); | ||
840 | } | ||
841 | } else { | ||
842 | int i; | ||
843 | for (i = 0; i < numpages; i++) { | ||
844 | if (addr[i] & ~PAGE_MASK) { | ||
845 | addr[i] &= PAGE_MASK; | ||
846 | WARN_ON_ONCE(1); | ||
847 | } | ||
848 | } | ||
778 | } | 849 | } |
779 | 850 | ||
780 | /* Must avoid aliasing mappings in the highmem code */ | 851 | /* Must avoid aliasing mappings in the highmem code */ |
@@ -784,9 +855,13 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
784 | cpa.numpages = numpages; | 855 | cpa.numpages = numpages; |
785 | cpa.mask_set = mask_set; | 856 | cpa.mask_set = mask_set; |
786 | cpa.mask_clr = mask_clr; | 857 | cpa.mask_clr = mask_clr; |
787 | cpa.flushtlb = 0; | 858 | cpa.flags = 0; |
859 | cpa.curpage = 0; | ||
788 | cpa.force_split = force_split; | 860 | cpa.force_split = force_split; |
789 | 861 | ||
862 | if (array) | ||
863 | cpa.flags |= CPA_ARRAY; | ||
864 | |||
790 | /* No alias checking for _NX bit modifications */ | 865 | /* No alias checking for _NX bit modifications */ |
791 | checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; | 866 | checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; |
792 | 867 | ||
@@ -795,7 +870,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
795 | /* | 870 | /* |
796 | * Check whether we really changed something: | 871 | * Check whether we really changed something: |
797 | */ | 872 | */ |
798 | if (!cpa.flushtlb) | 873 | if (!(cpa.flags & CPA_FLUSHTLB)) |
799 | goto out; | 874 | goto out; |
800 | 875 | ||
801 | /* | 876 | /* |
@@ -810,9 +885,12 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
810 | * error case we fall back to cpa_flush_all (which uses | 885 | * error case we fall back to cpa_flush_all (which uses |
811 | * wbindv): | 886 | * wbindv): |
812 | */ | 887 | */ |
813 | if (!ret && cpu_has_clflush) | 888 | if (!ret && cpu_has_clflush) { |
814 | cpa_flush_range(addr, numpages, cache); | 889 | if (cpa.flags & CPA_ARRAY) |
815 | else | 890 | cpa_flush_array(addr, numpages, cache); |
891 | else | ||
892 | cpa_flush_range(*addr, numpages, cache); | ||
893 | } else | ||
816 | cpa_flush_all(cache); | 894 | cpa_flush_all(cache); |
817 | 895 | ||
818 | out: | 896 | out: |
@@ -821,16 +899,18 @@ out: | |||
821 | return ret; | 899 | return ret; |
822 | } | 900 | } |
823 | 901 | ||
824 | static inline int change_page_attr_set(unsigned long addr, int numpages, | 902 | static inline int change_page_attr_set(unsigned long *addr, int numpages, |
825 | pgprot_t mask) | 903 | pgprot_t mask, int array) |
826 | { | 904 | { |
827 | return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0); | 905 | return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0, |
906 | array); | ||
828 | } | 907 | } |
829 | 908 | ||
830 | static inline int change_page_attr_clear(unsigned long addr, int numpages, | 909 | static inline int change_page_attr_clear(unsigned long *addr, int numpages, |
831 | pgprot_t mask) | 910 | pgprot_t mask, int array) |
832 | { | 911 | { |
833 | return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0); | 912 | return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0, |
913 | array); | ||
834 | } | 914 | } |
835 | 915 | ||
836 | int _set_memory_uc(unsigned long addr, int numpages) | 916 | int _set_memory_uc(unsigned long addr, int numpages) |
@@ -838,8 +918,8 @@ int _set_memory_uc(unsigned long addr, int numpages) | |||
838 | /* | 918 | /* |
839 | * for now UC MINUS. see comments in ioremap_nocache() | 919 | * for now UC MINUS. see comments in ioremap_nocache() |
840 | */ | 920 | */ |
841 | return change_page_attr_set(addr, numpages, | 921 | return change_page_attr_set(&addr, numpages, |
842 | __pgprot(_PAGE_CACHE_UC_MINUS)); | 922 | __pgprot(_PAGE_CACHE_UC_MINUS), 0); |
843 | } | 923 | } |
844 | 924 | ||
845 | int set_memory_uc(unsigned long addr, int numpages) | 925 | int set_memory_uc(unsigned long addr, int numpages) |
@@ -855,10 +935,31 @@ int set_memory_uc(unsigned long addr, int numpages) | |||
855 | } | 935 | } |
856 | EXPORT_SYMBOL(set_memory_uc); | 936 | EXPORT_SYMBOL(set_memory_uc); |
857 | 937 | ||
938 | int set_memory_array_uc(unsigned long *addr, int addrinarray) | ||
939 | { | ||
940 | int i; | ||
941 | /* | ||
942 | * for now UC MINUS. see comments in ioremap_nocache() | ||
943 | */ | ||
944 | for (i = 0; i < addrinarray; i++) { | ||
945 | if (reserve_memtype(addr[i], addr[i] + PAGE_SIZE, | ||
946 | _PAGE_CACHE_UC_MINUS, NULL)) | ||
947 | goto out; | ||
948 | } | ||
949 | |||
950 | return change_page_attr_set(addr, addrinarray, | ||
951 | __pgprot(_PAGE_CACHE_UC_MINUS), 1); | ||
952 | out: | ||
953 | while (--i >= 0) | ||
954 | free_memtype(addr[i], addr[i] + PAGE_SIZE); | ||
955 | return -EINVAL; | ||
956 | } | ||
957 | EXPORT_SYMBOL(set_memory_array_uc); | ||
958 | |||
858 | int _set_memory_wc(unsigned long addr, int numpages) | 959 | int _set_memory_wc(unsigned long addr, int numpages) |
859 | { | 960 | { |
860 | return change_page_attr_set(addr, numpages, | 961 | return change_page_attr_set(&addr, numpages, |
861 | __pgprot(_PAGE_CACHE_WC)); | 962 | __pgprot(_PAGE_CACHE_WC), 0); |
862 | } | 963 | } |
863 | 964 | ||
864 | int set_memory_wc(unsigned long addr, int numpages) | 965 | int set_memory_wc(unsigned long addr, int numpages) |
@@ -876,8 +977,8 @@ EXPORT_SYMBOL(set_memory_wc); | |||
876 | 977 | ||
877 | int _set_memory_wb(unsigned long addr, int numpages) | 978 | int _set_memory_wb(unsigned long addr, int numpages) |
878 | { | 979 | { |
879 | return change_page_attr_clear(addr, numpages, | 980 | return change_page_attr_clear(&addr, numpages, |
880 | __pgprot(_PAGE_CACHE_MASK)); | 981 | __pgprot(_PAGE_CACHE_MASK), 0); |
881 | } | 982 | } |
882 | 983 | ||
883 | int set_memory_wb(unsigned long addr, int numpages) | 984 | int set_memory_wb(unsigned long addr, int numpages) |
@@ -888,37 +989,48 @@ int set_memory_wb(unsigned long addr, int numpages) | |||
888 | } | 989 | } |
889 | EXPORT_SYMBOL(set_memory_wb); | 990 | EXPORT_SYMBOL(set_memory_wb); |
890 | 991 | ||
992 | int set_memory_array_wb(unsigned long *addr, int addrinarray) | ||
993 | { | ||
994 | int i; | ||
995 | for (i = 0; i < addrinarray; i++) | ||
996 | free_memtype(addr[i], addr[i] + PAGE_SIZE); | ||
997 | |||
998 | return change_page_attr_clear(addr, addrinarray, | ||
999 | __pgprot(_PAGE_CACHE_MASK), 1); | ||
1000 | } | ||
1001 | EXPORT_SYMBOL(set_memory_array_wb); | ||
1002 | |||
891 | int set_memory_x(unsigned long addr, int numpages) | 1003 | int set_memory_x(unsigned long addr, int numpages) |
892 | { | 1004 | { |
893 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_NX)); | 1005 | return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_NX), 0); |
894 | } | 1006 | } |
895 | EXPORT_SYMBOL(set_memory_x); | 1007 | EXPORT_SYMBOL(set_memory_x); |
896 | 1008 | ||
897 | int set_memory_nx(unsigned long addr, int numpages) | 1009 | int set_memory_nx(unsigned long addr, int numpages) |
898 | { | 1010 | { |
899 | return change_page_attr_set(addr, numpages, __pgprot(_PAGE_NX)); | 1011 | return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_NX), 0); |
900 | } | 1012 | } |
901 | EXPORT_SYMBOL(set_memory_nx); | 1013 | EXPORT_SYMBOL(set_memory_nx); |
902 | 1014 | ||
903 | int set_memory_ro(unsigned long addr, int numpages) | 1015 | int set_memory_ro(unsigned long addr, int numpages) |
904 | { | 1016 | { |
905 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW)); | 1017 | return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_RW), 0); |
906 | } | 1018 | } |
907 | 1019 | ||
908 | int set_memory_rw(unsigned long addr, int numpages) | 1020 | int set_memory_rw(unsigned long addr, int numpages) |
909 | { | 1021 | { |
910 | return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW)); | 1022 | return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_RW), 0); |
911 | } | 1023 | } |
912 | 1024 | ||
913 | int set_memory_np(unsigned long addr, int numpages) | 1025 | int set_memory_np(unsigned long addr, int numpages) |
914 | { | 1026 | { |
915 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT)); | 1027 | return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0); |
916 | } | 1028 | } |
917 | 1029 | ||
918 | int set_memory_4k(unsigned long addr, int numpages) | 1030 | int set_memory_4k(unsigned long addr, int numpages) |
919 | { | 1031 | { |
920 | return change_page_attr_set_clr(addr, numpages, __pgprot(0), | 1032 | return change_page_attr_set_clr(&addr, numpages, __pgprot(0), |
921 | __pgprot(0), 1); | 1033 | __pgprot(0), 1, 0); |
922 | } | 1034 | } |
923 | 1035 | ||
924 | int set_pages_uc(struct page *page, int numpages) | 1036 | int set_pages_uc(struct page *page, int numpages) |
@@ -971,20 +1083,24 @@ int set_pages_rw(struct page *page, int numpages) | |||
971 | 1083 | ||
972 | static int __set_pages_p(struct page *page, int numpages) | 1084 | static int __set_pages_p(struct page *page, int numpages) |
973 | { | 1085 | { |
974 | struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page), | 1086 | unsigned long tempaddr = (unsigned long) page_address(page); |
1087 | struct cpa_data cpa = { .vaddr = &tempaddr, | ||
975 | .numpages = numpages, | 1088 | .numpages = numpages, |
976 | .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), | 1089 | .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), |
977 | .mask_clr = __pgprot(0)}; | 1090 | .mask_clr = __pgprot(0), |
1091 | .flags = 0}; | ||
978 | 1092 | ||
979 | return __change_page_attr_set_clr(&cpa, 1); | 1093 | return __change_page_attr_set_clr(&cpa, 1); |
980 | } | 1094 | } |
981 | 1095 | ||
982 | static int __set_pages_np(struct page *page, int numpages) | 1096 | static int __set_pages_np(struct page *page, int numpages) |
983 | { | 1097 | { |
984 | struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page), | 1098 | unsigned long tempaddr = (unsigned long) page_address(page); |
1099 | struct cpa_data cpa = { .vaddr = &tempaddr, | ||
985 | .numpages = numpages, | 1100 | .numpages = numpages, |
986 | .mask_set = __pgprot(0), | 1101 | .mask_set = __pgprot(0), |
987 | .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)}; | 1102 | .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), |
1103 | .flags = 0}; | ||
988 | 1104 | ||
989 | return __change_page_attr_set_clr(&cpa, 1); | 1105 | return __change_page_attr_set_clr(&cpa, 1); |
990 | } | 1106 | } |
diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index f4c0ab50d2c..0a5f71817b3 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h | |||
@@ -66,6 +66,9 @@ int set_memory_rw(unsigned long addr, int numpages); | |||
66 | int set_memory_np(unsigned long addr, int numpages); | 66 | int set_memory_np(unsigned long addr, int numpages); |
67 | int set_memory_4k(unsigned long addr, int numpages); | 67 | int set_memory_4k(unsigned long addr, int numpages); |
68 | 68 | ||
69 | int set_memory_array_uc(unsigned long *addr, int addrinarray); | ||
70 | int set_memory_array_wb(unsigned long *addr, int addrinarray); | ||
71 | |||
69 | /* | 72 | /* |
70 | * For legacy compatibility with the old APIs, a few functions | 73 | * For legacy compatibility with the old APIs, a few functions |
71 | * are provided that work on a "struct page". | 74 | * are provided that work on a "struct page". |