aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mm/pageattr-test.c7
-rw-r--r--arch/x86/mm/pageattr.c219
-rw-r--r--arch/x86/mm/pat.c4
-rw-r--r--drivers/char/agp/agp.h5
-rw-r--r--drivers/char/agp/generic.c97
-rw-r--r--drivers/char/agp/intel-agp.c28
-rw-r--r--include/asm-x86/cacheflush.h3
-rw-r--r--mm/highmem.c5
8 files changed, 305 insertions, 63 deletions
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
index d4aa503caaa2..7c3017287119 100644
--- a/arch/x86/mm/pageattr-test.c
+++ b/arch/x86/mm/pageattr-test.c
@@ -118,6 +118,7 @@ static int pageattr_test(void)
118 unsigned int level; 118 unsigned int level;
119 int i, k; 119 int i, k;
120 int err; 120 int err;
121 unsigned long test_addr;
121 122
122 if (print) 123 if (print)
123 printk(KERN_INFO "CPA self-test:\n"); 124 printk(KERN_INFO "CPA self-test:\n");
@@ -172,7 +173,8 @@ static int pageattr_test(void)
172 continue; 173 continue;
173 } 174 }
174 175
175 err = change_page_attr_set(addr[i], len[i], PAGE_TESTBIT); 176 test_addr = addr[i];
177 err = change_page_attr_set(&test_addr, len[i], PAGE_TESTBIT, 0);
176 if (err < 0) { 178 if (err < 0) {
177 printk(KERN_ERR "CPA %d failed %d\n", i, err); 179 printk(KERN_ERR "CPA %d failed %d\n", i, err);
178 failed++; 180 failed++;
@@ -204,7 +206,8 @@ static int pageattr_test(void)
204 failed++; 206 failed++;
205 continue; 207 continue;
206 } 208 }
207 err = change_page_attr_clear(addr[i], len[i], PAGE_TESTBIT); 209 test_addr = addr[i];
210 err = change_page_attr_clear(&test_addr, len[i], PAGE_TESTBIT, 0);
208 if (err < 0) { 211 if (err < 0) {
209 printk(KERN_ERR "CPA reverting failed: %d\n", err); 212 printk(KERN_ERR "CPA reverting failed: %d\n", err);
210 failed++; 213 failed++;
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 43e2f8483e4f..1785591808bd 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 */
27struct cpa_data { 27struct 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
38static unsigned long direct_pages_count[PG_LEVEL_NUM]; 42static unsigned long direct_pages_count[PG_LEVEL_NUM];
39 43
@@ -190,6 +194,41 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache)
190 } 194 }
191} 195}
192 196
197static void cpa_flush_array(unsigned long *start, int numpages, int cache)
198{
199 unsigned int i, level;
200 unsigned long *addr;
201
202 BUG_ON(irqs_disabled());
203
204 on_each_cpu(__cpa_flush_range, NULL, 1);
205
206 if (!cache)
207 return;
208
209 /* 4M threshold */
210 if (numpages >= 1024) {
211 if (boot_cpu_data.x86_model >= 4)
212 wbinvd();
213 return;
214 }
215 /*
216 * We only need to flush on one CPU,
217 * clflush is a MESI-coherent instruction that
218 * will cause all other CPUs to flush the same
219 * cachelines:
220 */
221 for (i = 0, addr = start; i < numpages; i++, addr++) {
222 pte_t *pte = lookup_address(*addr, &level);
223
224 /*
225 * Only flush present addresses:
226 */
227 if (pte && (pte_val(*pte) & _PAGE_PRESENT))
228 clflush_cache_range((void *) *addr, PAGE_SIZE);
229 }
230}
231
193/* 232/*
194 * Certain areas of memory on x86 require very specific protection flags, 233 * Certain areas of memory on x86 require very specific protection flags,
195 * for example the BIOS area or kernel text. Callers don't always get this 234 * for example the BIOS area or kernel text. Callers don't always get this
@@ -398,7 +437,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
398 */ 437 */
399 new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot)); 438 new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot));
400 __set_pmd_pte(kpte, address, new_pte); 439 __set_pmd_pte(kpte, address, new_pte);
401 cpa->flushtlb = 1; 440 cpa->flags |= CPA_FLUSHTLB;
402 do_split = 0; 441 do_split = 0;
403 } 442 }
404 443
@@ -584,11 +623,16 @@ out_unlock:
584 623
585static int __change_page_attr(struct cpa_data *cpa, int primary) 624static int __change_page_attr(struct cpa_data *cpa, int primary)
586{ 625{
587 unsigned long address = cpa->vaddr; 626 unsigned long address;
588 int do_split, err; 627 int do_split, err;
589 unsigned int level; 628 unsigned int level;
590 pte_t *kpte, old_pte; 629 pte_t *kpte, old_pte;
591 630
631 if (cpa->flags & CPA_ARRAY)
632 address = cpa->vaddr[cpa->curpage];
633 else
634 address = *cpa->vaddr;
635
592repeat: 636repeat:
593 kpte = lookup_address(address, &level); 637 kpte = lookup_address(address, &level);
594 if (!kpte) 638 if (!kpte)
@@ -600,7 +644,7 @@ repeat:
600 return 0; 644 return 0;
601 WARN(1, KERN_WARNING "CPA: called for zero pte. " 645 WARN(1, KERN_WARNING "CPA: called for zero pte. "
602 "vaddr = %lx cpa->vaddr = %lx\n", address, 646 "vaddr = %lx cpa->vaddr = %lx\n", address,
603 cpa->vaddr); 647 *cpa->vaddr);
604 return -EINVAL; 648 return -EINVAL;
605 } 649 }
606 650
@@ -626,7 +670,7 @@ repeat:
626 */ 670 */
627 if (pte_val(old_pte) != pte_val(new_pte)) { 671 if (pte_val(old_pte) != pte_val(new_pte)) {
628 set_pte_atomic(kpte, new_pte); 672 set_pte_atomic(kpte, new_pte);
629 cpa->flushtlb = 1; 673 cpa->flags |= CPA_FLUSHTLB;
630 } 674 }
631 cpa->numpages = 1; 675 cpa->numpages = 1;
632 return 0; 676 return 0;
@@ -650,7 +694,7 @@ repeat:
650 */ 694 */
651 err = split_large_page(kpte, address); 695 err = split_large_page(kpte, address);
652 if (!err) { 696 if (!err) {
653 cpa->flushtlb = 1; 697 cpa->flags |= CPA_FLUSHTLB;
654 goto repeat; 698 goto repeat;
655 } 699 }
656 700
@@ -663,6 +707,7 @@ static int cpa_process_alias(struct cpa_data *cpa)
663{ 707{
664 struct cpa_data alias_cpa; 708 struct cpa_data alias_cpa;
665 int ret = 0; 709 int ret = 0;
710 unsigned long temp_cpa_vaddr, vaddr;
666 711
667 if (cpa->pfn >= max_pfn_mapped) 712 if (cpa->pfn >= max_pfn_mapped)
668 return 0; 713 return 0;
@@ -675,16 +720,24 @@ static int cpa_process_alias(struct cpa_data *cpa)
675 * No need to redo, when the primary call touched the direct 720 * No need to redo, when the primary call touched the direct
676 * mapping already: 721 * mapping already:
677 */ 722 */
678 if (!(within(cpa->vaddr, PAGE_OFFSET, 723 if (cpa->flags & CPA_ARRAY)
724 vaddr = cpa->vaddr[cpa->curpage];
725 else
726 vaddr = *cpa->vaddr;
727
728 if (!(within(vaddr, PAGE_OFFSET,
679 PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT)) 729 PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT))
680#ifdef CONFIG_X86_64 730#ifdef CONFIG_X86_64
681 || within(cpa->vaddr, PAGE_OFFSET + (1UL<<32), 731 || within(vaddr, PAGE_OFFSET + (1UL<<32),
682 PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)) 732 PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))
683#endif 733#endif
684 )) { 734 )) {
685 735
686 alias_cpa = *cpa; 736 alias_cpa = *cpa;
687 alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); 737 temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
738 alias_cpa.vaddr = &temp_cpa_vaddr;
739 alias_cpa.flags &= ~CPA_ARRAY;
740
688 741
689 ret = __change_page_attr_set_clr(&alias_cpa, 0); 742 ret = __change_page_attr_set_clr(&alias_cpa, 0);
690 } 743 }
@@ -696,7 +749,7 @@ static int cpa_process_alias(struct cpa_data *cpa)
696 * No need to redo, when the primary call touched the high 749 * No need to redo, when the primary call touched the high
697 * mapping already: 750 * mapping already:
698 */ 751 */
699 if (within(cpa->vaddr, (unsigned long) _text, (unsigned long) _end)) 752 if (within(vaddr, (unsigned long) _text, (unsigned long) _end))
700 return 0; 753 return 0;
701 754
702 /* 755 /*
@@ -707,8 +760,9 @@ static int cpa_process_alias(struct cpa_data *cpa)
707 return 0; 760 return 0;
708 761
709 alias_cpa = *cpa; 762 alias_cpa = *cpa;
710 alias_cpa.vaddr = 763 temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base;
711 (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; 764 alias_cpa.vaddr = &temp_cpa_vaddr;
765 alias_cpa.flags &= ~CPA_ARRAY;
712 766
713 /* 767 /*
714 * The high mapping range is imprecise, so ignore the return value. 768 * The high mapping range is imprecise, so ignore the return value.
@@ -728,6 +782,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
728 * preservation check. 782 * preservation check.
729 */ 783 */
730 cpa->numpages = numpages; 784 cpa->numpages = numpages;
785 /* for array changes, we can't use large page */
786 if (cpa->flags & CPA_ARRAY)
787 cpa->numpages = 1;
731 788
732 ret = __change_page_attr(cpa, checkalias); 789 ret = __change_page_attr(cpa, checkalias);
733 if (ret) 790 if (ret)
@@ -746,7 +803,11 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
746 */ 803 */
747 BUG_ON(cpa->numpages > numpages); 804 BUG_ON(cpa->numpages > numpages);
748 numpages -= cpa->numpages; 805 numpages -= cpa->numpages;
749 cpa->vaddr += cpa->numpages * PAGE_SIZE; 806 if (cpa->flags & CPA_ARRAY)
807 cpa->curpage++;
808 else
809 *cpa->vaddr += cpa->numpages * PAGE_SIZE;
810
750 } 811 }
751 return 0; 812 return 0;
752} 813}
@@ -757,9 +818,9 @@ static inline int cache_attr(pgprot_t attr)
757 (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); 818 (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD);
758} 819}
759 820
760static int change_page_attr_set_clr(unsigned long addr, int numpages, 821static int change_page_attr_set_clr(unsigned long *addr, int numpages,
761 pgprot_t mask_set, pgprot_t mask_clr, 822 pgprot_t mask_set, pgprot_t mask_clr,
762 int force_split) 823 int force_split, int array)
763{ 824{
764 struct cpa_data cpa; 825 struct cpa_data cpa;
765 int ret, cache, checkalias; 826 int ret, cache, checkalias;
@@ -774,21 +835,38 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
774 return 0; 835 return 0;
775 836
776 /* Ensure we are PAGE_SIZE aligned */ 837 /* Ensure we are PAGE_SIZE aligned */
777 if (addr & ~PAGE_MASK) { 838 if (!array) {
778 addr &= PAGE_MASK; 839 if (*addr & ~PAGE_MASK) {
779 /* 840 *addr &= PAGE_MASK;
780 * People should not be passing in unaligned addresses: 841 /*
781 */ 842 * People should not be passing in unaligned addresses:
782 WARN_ON_ONCE(1); 843 */
844 WARN_ON_ONCE(1);
845 }
846 } else {
847 int i;
848 for (i = 0; i < numpages; i++) {
849 if (addr[i] & ~PAGE_MASK) {
850 addr[i] &= PAGE_MASK;
851 WARN_ON_ONCE(1);
852 }
853 }
783 } 854 }
784 855
856 /* Must avoid aliasing mappings in the highmem code */
857 kmap_flush_unused();
858
785 cpa.vaddr = addr; 859 cpa.vaddr = addr;
786 cpa.numpages = numpages; 860 cpa.numpages = numpages;
787 cpa.mask_set = mask_set; 861 cpa.mask_set = mask_set;
788 cpa.mask_clr = mask_clr; 862 cpa.mask_clr = mask_clr;
789 cpa.flushtlb = 0; 863 cpa.flags = 0;
864 cpa.curpage = 0;
790 cpa.force_split = force_split; 865 cpa.force_split = force_split;
791 866
867 if (array)
868 cpa.flags |= CPA_ARRAY;
869
792 /* No alias checking for _NX bit modifications */ 870 /* No alias checking for _NX bit modifications */
793 checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; 871 checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
794 872
@@ -797,7 +875,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
797 /* 875 /*
798 * Check whether we really changed something: 876 * Check whether we really changed something:
799 */ 877 */
800 if (!cpa.flushtlb) 878 if (!(cpa.flags & CPA_FLUSHTLB))
801 goto out; 879 goto out;
802 880
803 /* 881 /*
@@ -812,9 +890,12 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
812 * error case we fall back to cpa_flush_all (which uses 890 * error case we fall back to cpa_flush_all (which uses
813 * wbindv): 891 * wbindv):
814 */ 892 */
815 if (!ret && cpu_has_clflush) 893 if (!ret && cpu_has_clflush) {
816 cpa_flush_range(addr, numpages, cache); 894 if (cpa.flags & CPA_ARRAY)
817 else 895 cpa_flush_array(addr, numpages, cache);
896 else
897 cpa_flush_range(*addr, numpages, cache);
898 } else
818 cpa_flush_all(cache); 899 cpa_flush_all(cache);
819 900
820out: 901out:
@@ -823,16 +904,18 @@ out:
823 return ret; 904 return ret;
824} 905}
825 906
826static inline int change_page_attr_set(unsigned long addr, int numpages, 907static inline int change_page_attr_set(unsigned long *addr, int numpages,
827 pgprot_t mask) 908 pgprot_t mask, int array)
828{ 909{
829 return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0); 910 return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0,
911 array);
830} 912}
831 913
832static inline int change_page_attr_clear(unsigned long addr, int numpages, 914static inline int change_page_attr_clear(unsigned long *addr, int numpages,
833 pgprot_t mask) 915 pgprot_t mask, int array)
834{ 916{
835 return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0); 917 return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0,
918 array);
836} 919}
837 920
838int _set_memory_uc(unsigned long addr, int numpages) 921int _set_memory_uc(unsigned long addr, int numpages)
@@ -840,8 +923,8 @@ int _set_memory_uc(unsigned long addr, int numpages)
840 /* 923 /*
841 * for now UC MINUS. see comments in ioremap_nocache() 924 * for now UC MINUS. see comments in ioremap_nocache()
842 */ 925 */
843 return change_page_attr_set(addr, numpages, 926 return change_page_attr_set(&addr, numpages,
844 __pgprot(_PAGE_CACHE_UC_MINUS)); 927 __pgprot(_PAGE_CACHE_UC_MINUS), 0);
845} 928}
846 929
847int set_memory_uc(unsigned long addr, int numpages) 930int set_memory_uc(unsigned long addr, int numpages)
@@ -857,10 +940,31 @@ int set_memory_uc(unsigned long addr, int numpages)
857} 940}
858EXPORT_SYMBOL(set_memory_uc); 941EXPORT_SYMBOL(set_memory_uc);
859 942
943int set_memory_array_uc(unsigned long *addr, int addrinarray)
944{
945 int i;
946 /*
947 * for now UC MINUS. see comments in ioremap_nocache()
948 */
949 for (i = 0; i < addrinarray; i++) {
950 if (reserve_memtype(addr[i], addr[i] + PAGE_SIZE,
951 _PAGE_CACHE_UC_MINUS, NULL))
952 goto out;
953 }
954
955 return change_page_attr_set(addr, addrinarray,
956 __pgprot(_PAGE_CACHE_UC_MINUS), 1);
957out:
958 while (--i >= 0)
959 free_memtype(addr[i], addr[i] + PAGE_SIZE);
960 return -EINVAL;
961}
962EXPORT_SYMBOL(set_memory_array_uc);
963
860int _set_memory_wc(unsigned long addr, int numpages) 964int _set_memory_wc(unsigned long addr, int numpages)
861{ 965{
862 return change_page_attr_set(addr, numpages, 966 return change_page_attr_set(&addr, numpages,
863 __pgprot(_PAGE_CACHE_WC)); 967 __pgprot(_PAGE_CACHE_WC), 0);
864} 968}
865 969
866int set_memory_wc(unsigned long addr, int numpages) 970int set_memory_wc(unsigned long addr, int numpages)
@@ -878,8 +982,8 @@ EXPORT_SYMBOL(set_memory_wc);
878 982
879int _set_memory_wb(unsigned long addr, int numpages) 983int _set_memory_wb(unsigned long addr, int numpages)
880{ 984{
881 return change_page_attr_clear(addr, numpages, 985 return change_page_attr_clear(&addr, numpages,
882 __pgprot(_PAGE_CACHE_MASK)); 986 __pgprot(_PAGE_CACHE_MASK), 0);
883} 987}
884 988
885int set_memory_wb(unsigned long addr, int numpages) 989int set_memory_wb(unsigned long addr, int numpages)
@@ -890,37 +994,48 @@ int set_memory_wb(unsigned long addr, int numpages)
890} 994}
891EXPORT_SYMBOL(set_memory_wb); 995EXPORT_SYMBOL(set_memory_wb);
892 996
997int set_memory_array_wb(unsigned long *addr, int addrinarray)
998{
999 int i;
1000 for (i = 0; i < addrinarray; i++)
1001 free_memtype(addr[i], addr[i] + PAGE_SIZE);
1002
1003 return change_page_attr_clear(addr, addrinarray,
1004 __pgprot(_PAGE_CACHE_MASK), 1);
1005}
1006EXPORT_SYMBOL(set_memory_array_wb);
1007
893int set_memory_x(unsigned long addr, int numpages) 1008int set_memory_x(unsigned long addr, int numpages)
894{ 1009{
895 return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_NX)); 1010 return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_NX), 0);
896} 1011}
897EXPORT_SYMBOL(set_memory_x); 1012EXPORT_SYMBOL(set_memory_x);
898 1013
899int set_memory_nx(unsigned long addr, int numpages) 1014int set_memory_nx(unsigned long addr, int numpages)
900{ 1015{
901 return change_page_attr_set(addr, numpages, __pgprot(_PAGE_NX)); 1016 return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_NX), 0);
902} 1017}
903EXPORT_SYMBOL(set_memory_nx); 1018EXPORT_SYMBOL(set_memory_nx);
904 1019
905int set_memory_ro(unsigned long addr, int numpages) 1020int set_memory_ro(unsigned long addr, int numpages)
906{ 1021{
907 return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW)); 1022 return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_RW), 0);
908} 1023}
909 1024
910int set_memory_rw(unsigned long addr, int numpages) 1025int set_memory_rw(unsigned long addr, int numpages)
911{ 1026{
912 return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW)); 1027 return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_RW), 0);
913} 1028}
914 1029
915int set_memory_np(unsigned long addr, int numpages) 1030int set_memory_np(unsigned long addr, int numpages)
916{ 1031{
917 return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT)); 1032 return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0);
918} 1033}
919 1034
920int set_memory_4k(unsigned long addr, int numpages) 1035int set_memory_4k(unsigned long addr, int numpages)
921{ 1036{
922 return change_page_attr_set_clr(addr, numpages, __pgprot(0), 1037 return change_page_attr_set_clr(&addr, numpages, __pgprot(0),
923 __pgprot(0), 1); 1038 __pgprot(0), 1, 0);
924} 1039}
925 1040
926int set_pages_uc(struct page *page, int numpages) 1041int set_pages_uc(struct page *page, int numpages)
@@ -973,20 +1088,24 @@ int set_pages_rw(struct page *page, int numpages)
973 1088
974static int __set_pages_p(struct page *page, int numpages) 1089static int __set_pages_p(struct page *page, int numpages)
975{ 1090{
976 struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page), 1091 unsigned long tempaddr = (unsigned long) page_address(page);
1092 struct cpa_data cpa = { .vaddr = &tempaddr,
977 .numpages = numpages, 1093 .numpages = numpages,
978 .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), 1094 .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
979 .mask_clr = __pgprot(0)}; 1095 .mask_clr = __pgprot(0),
1096 .flags = 0};
980 1097
981 return __change_page_attr_set_clr(&cpa, 1); 1098 return __change_page_attr_set_clr(&cpa, 1);
982} 1099}
983 1100
984static int __set_pages_np(struct page *page, int numpages) 1101static int __set_pages_np(struct page *page, int numpages)
985{ 1102{
986 struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page), 1103 unsigned long tempaddr = (unsigned long) page_address(page);
1104 struct cpa_data cpa = { .vaddr = &tempaddr,
987 .numpages = numpages, 1105 .numpages = numpages,
988 .mask_set = __pgprot(0), 1106 .mask_set = __pgprot(0),
989 .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)}; 1107 .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW),
1108 .flags = 0};
990 1109
991 return __change_page_attr_set_clr(&cpa, 1); 1110 return __change_page_attr_set_clr(&cpa, 1);
992} 1111}
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 2a50e0fa64a5..f049b1d6ebdf 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -514,7 +514,7 @@ void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
514 free_memtype(addr, addr + size); 514 free_memtype(addr, addr + size);
515} 515}
516 516
517#if defined(CONFIG_DEBUG_FS) 517#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
518 518
519/* get Nth element of the linked list */ 519/* get Nth element of the linked list */
520static struct memtype *memtype_get_idx(loff_t pos) 520static struct memtype *memtype_get_idx(loff_t pos)
@@ -598,4 +598,4 @@ static int __init pat_memtype_list_init(void)
598 598
599late_initcall(pat_memtype_list_init); 599late_initcall(pat_memtype_list_init);
600 600
601#endif /* CONFIG_DEBUG_FS */ 601#endif /* CONFIG_DEBUG_FS && CONFIG_X86_PAT */
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 4bada0e8b812..46f507531177 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -116,7 +116,9 @@ struct agp_bridge_driver {
116 struct agp_memory *(*alloc_by_type) (size_t, int); 116 struct agp_memory *(*alloc_by_type) (size_t, int);
117 void (*free_by_type)(struct agp_memory *); 117 void (*free_by_type)(struct agp_memory *);
118 void *(*agp_alloc_page)(struct agp_bridge_data *); 118 void *(*agp_alloc_page)(struct agp_bridge_data *);
119 int (*agp_alloc_pages)(struct agp_bridge_data *, struct agp_memory *, size_t);
119 void (*agp_destroy_page)(void *, int flags); 120 void (*agp_destroy_page)(void *, int flags);
121 void (*agp_destroy_pages)(struct agp_memory *);
120 int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); 122 int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
121 void (*chipset_flush)(struct agp_bridge_data *); 123 void (*chipset_flush)(struct agp_bridge_data *);
122}; 124};
@@ -277,7 +279,10 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
277struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type); 279struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
278void agp_generic_free_by_type(struct agp_memory *curr); 280void agp_generic_free_by_type(struct agp_memory *curr);
279void *agp_generic_alloc_page(struct agp_bridge_data *bridge); 281void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
282int agp_generic_alloc_pages(struct agp_bridge_data *agp_bridge,
283 struct agp_memory *memory, size_t page_count);
280void agp_generic_destroy_page(void *addr, int flags); 284void agp_generic_destroy_page(void *addr, int flags);
285void agp_generic_destroy_pages(struct agp_memory *memory);
281void agp_free_key(int key); 286void agp_free_key(int key);
282int agp_num_entries(void); 287int agp_num_entries(void);
283u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command); 288u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 118dbde25dc7..10d6cbd7c05e 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -201,14 +201,22 @@ void agp_free_memory(struct agp_memory *curr)
201 return; 201 return;
202 } 202 }
203 if (curr->page_count != 0) { 203 if (curr->page_count != 0) {
204 for (i = 0; i < curr->page_count; i++) { 204 if (curr->bridge->driver->agp_destroy_pages) {
205 curr->memory[i] = (unsigned long)gart_to_virt(curr->memory[i]); 205 curr->bridge->driver->agp_destroy_pages(curr);
206 curr->bridge->driver->agp_destroy_page((void *)curr->memory[i], 206 } else {
207 AGP_PAGE_DESTROY_UNMAP); 207
208 } 208 for (i = 0; i < curr->page_count; i++) {
209 for (i = 0; i < curr->page_count; i++) { 209 curr->memory[i] = (unsigned long)gart_to_virt(
210 curr->bridge->driver->agp_destroy_page((void *)curr->memory[i], 210 curr->memory[i]);
211 AGP_PAGE_DESTROY_FREE); 211 curr->bridge->driver->agp_destroy_page(
212 (void *)curr->memory[i],
213 AGP_PAGE_DESTROY_UNMAP);
214 }
215 for (i = 0; i < curr->page_count; i++) {
216 curr->bridge->driver->agp_destroy_page(
217 (void *)curr->memory[i],
218 AGP_PAGE_DESTROY_FREE);
219 }
212 } 220 }
213 } 221 }
214 agp_free_key(curr->key); 222 agp_free_key(curr->key);
@@ -264,6 +272,15 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
264 if (new == NULL) 272 if (new == NULL)
265 return NULL; 273 return NULL;
266 274
275 if (bridge->driver->agp_alloc_pages) {
276 if (bridge->driver->agp_alloc_pages(bridge, new, page_count)) {
277 agp_free_memory(new);
278 return NULL;
279 }
280 new->bridge = bridge;
281 return new;
282 }
283
267 for (i = 0; i < page_count; i++) { 284 for (i = 0; i < page_count; i++) {
268 void *addr = bridge->driver->agp_alloc_page(bridge); 285 void *addr = bridge->driver->agp_alloc_page(bridge);
269 286
@@ -1203,6 +1220,39 @@ EXPORT_SYMBOL(agp_generic_alloc_user);
1203 * against a maximum value. 1220 * against a maximum value.
1204 */ 1221 */
1205 1222
1223int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *mem, size_t num_pages)
1224{
1225 struct page * page;
1226 int i, ret = -ENOMEM;
1227
1228 for (i = 0; i < num_pages; i++) {
1229 page = alloc_page(GFP_KERNEL | GFP_DMA32);
1230 /* agp_free_memory() needs gart address */
1231 if (page == NULL)
1232 goto out;
1233
1234#ifndef CONFIG_X86
1235 map_page_into_agp(page);
1236#endif
1237 get_page(page);
1238 atomic_inc(&agp_bridge->current_memory_agp);
1239
1240 /* set_memory_array_uc() needs virtual address */
1241 mem->memory[i] = (unsigned long)page_address(page);
1242 mem->page_count++;
1243 }
1244
1245#ifdef CONFIG_X86
1246 set_memory_array_uc(mem->memory, num_pages);
1247#endif
1248 ret = 0;
1249out:
1250 for (i = 0; i < mem->page_count; i++)
1251 mem->memory[i] = virt_to_gart((void *)mem->memory[i]);
1252 return ret;
1253}
1254EXPORT_SYMBOL(agp_generic_alloc_pages);
1255
1206void *agp_generic_alloc_page(struct agp_bridge_data *bridge) 1256void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
1207{ 1257{
1208 struct page * page; 1258 struct page * page;
@@ -1219,6 +1269,37 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
1219} 1269}
1220EXPORT_SYMBOL(agp_generic_alloc_page); 1270EXPORT_SYMBOL(agp_generic_alloc_page);
1221 1271
1272void agp_generic_destroy_pages(struct agp_memory *mem)
1273{
1274 int i;
1275 void *addr;
1276 struct page *page;
1277
1278 if (!mem)
1279 return;
1280
1281 for (i = 0; i < mem->page_count; i++)
1282 mem->memory[i] = (unsigned long)gart_to_virt(mem->memory[i]);
1283
1284#ifdef CONFIG_X86
1285 set_memory_array_wb(mem->memory, mem->page_count);
1286#endif
1287
1288 for (i = 0; i < mem->page_count; i++) {
1289 addr = (void *)mem->memory[i];
1290 page = virt_to_page(addr);
1291
1292#ifndef CONFIG_X86
1293 unmap_page_from_agp(page);
1294#endif
1295
1296 put_page(page);
1297 free_page((unsigned long)addr);
1298 atomic_dec(&agp_bridge->current_memory_agp);
1299 mem->memory[i] = 0;
1300 }
1301}
1302EXPORT_SYMBOL(agp_generic_destroy_pages);
1222 1303
1223void agp_generic_destroy_page(void *addr, int flags) 1304void agp_generic_destroy_page(void *addr, int flags)
1224{ 1305{
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 016fdf0623a4..043e36628d6d 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -1711,7 +1711,9 @@ static const struct agp_bridge_driver intel_generic_driver = {
1711 .alloc_by_type = agp_generic_alloc_by_type, 1711 .alloc_by_type = agp_generic_alloc_by_type,
1712 .free_by_type = agp_generic_free_by_type, 1712 .free_by_type = agp_generic_free_by_type,
1713 .agp_alloc_page = agp_generic_alloc_page, 1713 .agp_alloc_page = agp_generic_alloc_page,
1714 .agp_alloc_pages = agp_generic_alloc_pages,
1714 .agp_destroy_page = agp_generic_destroy_page, 1715 .agp_destroy_page = agp_generic_destroy_page,
1716 .agp_destroy_pages = agp_generic_destroy_pages,
1715 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1717 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1716}; 1718};
1717 1719
@@ -1736,7 +1738,9 @@ static const struct agp_bridge_driver intel_810_driver = {
1736 .alloc_by_type = intel_i810_alloc_by_type, 1738 .alloc_by_type = intel_i810_alloc_by_type,
1737 .free_by_type = intel_i810_free_by_type, 1739 .free_by_type = intel_i810_free_by_type,
1738 .agp_alloc_page = agp_generic_alloc_page, 1740 .agp_alloc_page = agp_generic_alloc_page,
1741 .agp_alloc_pages = agp_generic_alloc_pages,
1739 .agp_destroy_page = agp_generic_destroy_page, 1742 .agp_destroy_page = agp_generic_destroy_page,
1743 .agp_destroy_pages = agp_generic_destroy_pages,
1740 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1744 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1741}; 1745};
1742 1746
@@ -1760,7 +1764,9 @@ static const struct agp_bridge_driver intel_815_driver = {
1760 .alloc_by_type = agp_generic_alloc_by_type, 1764 .alloc_by_type = agp_generic_alloc_by_type,
1761 .free_by_type = agp_generic_free_by_type, 1765 .free_by_type = agp_generic_free_by_type,
1762 .agp_alloc_page = agp_generic_alloc_page, 1766 .agp_alloc_page = agp_generic_alloc_page,
1767 .agp_alloc_pages = agp_generic_alloc_pages,
1763 .agp_destroy_page = agp_generic_destroy_page, 1768 .agp_destroy_page = agp_generic_destroy_page,
1769 .agp_destroy_pages = agp_generic_destroy_pages,
1764 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1770 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1765}; 1771};
1766 1772
@@ -1785,7 +1791,9 @@ static const struct agp_bridge_driver intel_830_driver = {
1785 .alloc_by_type = intel_i830_alloc_by_type, 1791 .alloc_by_type = intel_i830_alloc_by_type,
1786 .free_by_type = intel_i810_free_by_type, 1792 .free_by_type = intel_i810_free_by_type,
1787 .agp_alloc_page = agp_generic_alloc_page, 1793 .agp_alloc_page = agp_generic_alloc_page,
1794 .agp_alloc_pages = agp_generic_alloc_pages,
1788 .agp_destroy_page = agp_generic_destroy_page, 1795 .agp_destroy_page = agp_generic_destroy_page,
1796 .agp_destroy_pages = agp_generic_destroy_pages,
1789 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1797 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1790 .chipset_flush = intel_i830_chipset_flush, 1798 .chipset_flush = intel_i830_chipset_flush,
1791}; 1799};
@@ -1810,7 +1818,9 @@ static const struct agp_bridge_driver intel_820_driver = {
1810 .alloc_by_type = agp_generic_alloc_by_type, 1818 .alloc_by_type = agp_generic_alloc_by_type,
1811 .free_by_type = agp_generic_free_by_type, 1819 .free_by_type = agp_generic_free_by_type,
1812 .agp_alloc_page = agp_generic_alloc_page, 1820 .agp_alloc_page = agp_generic_alloc_page,
1821 .agp_alloc_pages = agp_generic_alloc_pages,
1813 .agp_destroy_page = agp_generic_destroy_page, 1822 .agp_destroy_page = agp_generic_destroy_page,
1823 .agp_destroy_pages = agp_generic_destroy_pages,
1814 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1824 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1815}; 1825};
1816 1826
@@ -1834,7 +1844,9 @@ static const struct agp_bridge_driver intel_830mp_driver = {
1834 .alloc_by_type = agp_generic_alloc_by_type, 1844 .alloc_by_type = agp_generic_alloc_by_type,
1835 .free_by_type = agp_generic_free_by_type, 1845 .free_by_type = agp_generic_free_by_type,
1836 .agp_alloc_page = agp_generic_alloc_page, 1846 .agp_alloc_page = agp_generic_alloc_page,
1847 .agp_alloc_pages = agp_generic_alloc_pages,
1837 .agp_destroy_page = agp_generic_destroy_page, 1848 .agp_destroy_page = agp_generic_destroy_page,
1849 .agp_destroy_pages = agp_generic_destroy_pages,
1838 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1850 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1839}; 1851};
1840 1852
@@ -1858,7 +1870,9 @@ static const struct agp_bridge_driver intel_840_driver = {
1858 .alloc_by_type = agp_generic_alloc_by_type, 1870 .alloc_by_type = agp_generic_alloc_by_type,
1859 .free_by_type = agp_generic_free_by_type, 1871 .free_by_type = agp_generic_free_by_type,
1860 .agp_alloc_page = agp_generic_alloc_page, 1872 .agp_alloc_page = agp_generic_alloc_page,
1873 .agp_alloc_pages = agp_generic_alloc_pages,
1861 .agp_destroy_page = agp_generic_destroy_page, 1874 .agp_destroy_page = agp_generic_destroy_page,
1875 .agp_destroy_pages = agp_generic_destroy_pages,
1862 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1876 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1863}; 1877};
1864 1878
@@ -1882,7 +1896,9 @@ static const struct agp_bridge_driver intel_845_driver = {
1882 .alloc_by_type = agp_generic_alloc_by_type, 1896 .alloc_by_type = agp_generic_alloc_by_type,
1883 .free_by_type = agp_generic_free_by_type, 1897 .free_by_type = agp_generic_free_by_type,
1884 .agp_alloc_page = agp_generic_alloc_page, 1898 .agp_alloc_page = agp_generic_alloc_page,
1899 .agp_alloc_pages = agp_generic_alloc_pages,
1885 .agp_destroy_page = agp_generic_destroy_page, 1900 .agp_destroy_page = agp_generic_destroy_page,
1901 .agp_destroy_pages = agp_generic_destroy_pages,
1886 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1902 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1887 .chipset_flush = intel_i830_chipset_flush, 1903 .chipset_flush = intel_i830_chipset_flush,
1888}; 1904};
@@ -1907,7 +1923,9 @@ static const struct agp_bridge_driver intel_850_driver = {
1907 .alloc_by_type = agp_generic_alloc_by_type, 1923 .alloc_by_type = agp_generic_alloc_by_type,
1908 .free_by_type = agp_generic_free_by_type, 1924 .free_by_type = agp_generic_free_by_type,
1909 .agp_alloc_page = agp_generic_alloc_page, 1925 .agp_alloc_page = agp_generic_alloc_page,
1926 .agp_alloc_pages = agp_generic_alloc_pages,
1910 .agp_destroy_page = agp_generic_destroy_page, 1927 .agp_destroy_page = agp_generic_destroy_page,
1928 .agp_destroy_pages = agp_generic_destroy_pages,
1911 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1929 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1912}; 1930};
1913 1931
@@ -1931,7 +1949,9 @@ static const struct agp_bridge_driver intel_860_driver = {
1931 .alloc_by_type = agp_generic_alloc_by_type, 1949 .alloc_by_type = agp_generic_alloc_by_type,
1932 .free_by_type = agp_generic_free_by_type, 1950 .free_by_type = agp_generic_free_by_type,
1933 .agp_alloc_page = agp_generic_alloc_page, 1951 .agp_alloc_page = agp_generic_alloc_page,
1952 .agp_alloc_pages = agp_generic_alloc_pages,
1934 .agp_destroy_page = agp_generic_destroy_page, 1953 .agp_destroy_page = agp_generic_destroy_page,
1954 .agp_destroy_pages = agp_generic_destroy_pages,
1935 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1955 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1936}; 1956};
1937 1957
@@ -1956,7 +1976,9 @@ static const struct agp_bridge_driver intel_915_driver = {
1956 .alloc_by_type = intel_i830_alloc_by_type, 1976 .alloc_by_type = intel_i830_alloc_by_type,
1957 .free_by_type = intel_i810_free_by_type, 1977 .free_by_type = intel_i810_free_by_type,
1958 .agp_alloc_page = agp_generic_alloc_page, 1978 .agp_alloc_page = agp_generic_alloc_page,
1979 .agp_alloc_pages = agp_generic_alloc_pages,
1959 .agp_destroy_page = agp_generic_destroy_page, 1980 .agp_destroy_page = agp_generic_destroy_page,
1981 .agp_destroy_pages = agp_generic_destroy_pages,
1960 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1982 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1961 .chipset_flush = intel_i915_chipset_flush, 1983 .chipset_flush = intel_i915_chipset_flush,
1962}; 1984};
@@ -1982,7 +2004,9 @@ static const struct agp_bridge_driver intel_i965_driver = {
1982 .alloc_by_type = intel_i830_alloc_by_type, 2004 .alloc_by_type = intel_i830_alloc_by_type,
1983 .free_by_type = intel_i810_free_by_type, 2005 .free_by_type = intel_i810_free_by_type,
1984 .agp_alloc_page = agp_generic_alloc_page, 2006 .agp_alloc_page = agp_generic_alloc_page,
2007 .agp_alloc_pages = agp_generic_alloc_pages,
1985 .agp_destroy_page = agp_generic_destroy_page, 2008 .agp_destroy_page = agp_generic_destroy_page,
2009 .agp_destroy_pages = agp_generic_destroy_pages,
1986 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 2010 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1987 .chipset_flush = intel_i915_chipset_flush, 2011 .chipset_flush = intel_i915_chipset_flush,
1988}; 2012};
@@ -2007,7 +2031,9 @@ static const struct agp_bridge_driver intel_7505_driver = {
2007 .alloc_by_type = agp_generic_alloc_by_type, 2031 .alloc_by_type = agp_generic_alloc_by_type,
2008 .free_by_type = agp_generic_free_by_type, 2032 .free_by_type = agp_generic_free_by_type,
2009 .agp_alloc_page = agp_generic_alloc_page, 2033 .agp_alloc_page = agp_generic_alloc_page,
2034 .agp_alloc_pages = agp_generic_alloc_pages,
2010 .agp_destroy_page = agp_generic_destroy_page, 2035 .agp_destroy_page = agp_generic_destroy_page,
2036 .agp_destroy_pages = agp_generic_destroy_pages,
2011 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 2037 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
2012}; 2038};
2013 2039
@@ -2032,7 +2058,9 @@ static const struct agp_bridge_driver intel_g33_driver = {
2032 .alloc_by_type = intel_i830_alloc_by_type, 2058 .alloc_by_type = intel_i830_alloc_by_type,
2033 .free_by_type = intel_i810_free_by_type, 2059 .free_by_type = intel_i810_free_by_type,
2034 .agp_alloc_page = agp_generic_alloc_page, 2060 .agp_alloc_page = agp_generic_alloc_page,
2061 .agp_alloc_pages = agp_generic_alloc_pages,
2035 .agp_destroy_page = agp_generic_destroy_page, 2062 .agp_destroy_page = agp_generic_destroy_page,
2063 .agp_destroy_pages = agp_generic_destroy_pages,
2036 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 2064 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
2037 .chipset_flush = intel_i915_chipset_flush, 2065 .chipset_flush = intel_i915_chipset_flush,
2038}; 2066};
diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h
index f4c0ab50d2c2..0a5f71817b3e 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);
66int set_memory_np(unsigned long addr, int numpages); 66int set_memory_np(unsigned long addr, int numpages);
67int set_memory_4k(unsigned long addr, int numpages); 67int set_memory_4k(unsigned long addr, int numpages);
68 68
69int set_memory_array_uc(unsigned long *addr, int addrinarray);
70int 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".
diff --git a/mm/highmem.c b/mm/highmem.c
index e16e1523b688..b36b83b920ff 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -70,6 +70,7 @@ static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait);
70static void flush_all_zero_pkmaps(void) 70static void flush_all_zero_pkmaps(void)
71{ 71{
72 int i; 72 int i;
73 int need_flush = 0;
73 74
74 flush_cache_kmaps(); 75 flush_cache_kmaps();
75 76
@@ -101,8 +102,10 @@ static void flush_all_zero_pkmaps(void)
101 &pkmap_page_table[i]); 102 &pkmap_page_table[i]);
102 103
103 set_page_address(page, NULL); 104 set_page_address(page, NULL);
105 need_flush = 1;
104 } 106 }
105 flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP)); 107 if (need_flush)
108 flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP));
106} 109}
107 110
108/** 111/**