diff options
| -rw-r--r-- | arch/x86/include/asm/cacheflush.h | 3 | ||||
| -rw-r--r-- | arch/x86/mm/pageattr.c | 63 |
2 files changed, 66 insertions, 0 deletions
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h index 5b301b7ff5f4..b3894bf52fcd 100644 --- a/arch/x86/include/asm/cacheflush.h +++ b/arch/x86/include/asm/cacheflush.h | |||
| @@ -90,6 +90,9 @@ int set_memory_4k(unsigned long addr, int numpages); | |||
| 90 | int set_memory_array_uc(unsigned long *addr, int addrinarray); | 90 | int set_memory_array_uc(unsigned long *addr, int addrinarray); |
| 91 | int set_memory_array_wb(unsigned long *addr, int addrinarray); | 91 | int set_memory_array_wb(unsigned long *addr, int addrinarray); |
| 92 | 92 | ||
| 93 | int set_pages_array_uc(struct page **pages, int addrinarray); | ||
| 94 | int set_pages_array_wb(struct page **pages, int addrinarray); | ||
| 95 | |||
| 93 | /* | 96 | /* |
| 94 | * For legacy compatibility with the old APIs, a few functions | 97 | * For legacy compatibility with the old APIs, a few functions |
| 95 | * are provided that work on a "struct page". | 98 | * are provided that work on a "struct page". |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index e5c257fb41e2..d71e1b636ce6 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
| @@ -920,6 +920,20 @@ static inline int change_page_attr_clear(unsigned long *addr, int numpages, | |||
| 920 | (array ? CPA_ARRAY : 0), NULL); | 920 | (array ? CPA_ARRAY : 0), NULL); |
| 921 | } | 921 | } |
| 922 | 922 | ||
| 923 | static inline int cpa_set_pages_array(struct page **pages, int numpages, | ||
| 924 | pgprot_t mask) | ||
| 925 | { | ||
| 926 | return change_page_attr_set_clr(NULL, numpages, mask, __pgprot(0), 0, | ||
| 927 | CPA_PAGES_ARRAY, pages); | ||
| 928 | } | ||
| 929 | |||
| 930 | static inline int cpa_clear_pages_array(struct page **pages, int numpages, | ||
| 931 | pgprot_t mask) | ||
| 932 | { | ||
| 933 | return change_page_attr_set_clr(NULL, numpages, __pgprot(0), mask, 0, | ||
| 934 | CPA_PAGES_ARRAY, pages); | ||
| 935 | } | ||
| 936 | |||
| 923 | int _set_memory_uc(unsigned long addr, int numpages) | 937 | int _set_memory_uc(unsigned long addr, int numpages) |
| 924 | { | 938 | { |
| 925 | /* | 939 | /* |
| @@ -1076,6 +1090,35 @@ int set_pages_uc(struct page *page, int numpages) | |||
| 1076 | } | 1090 | } |
| 1077 | EXPORT_SYMBOL(set_pages_uc); | 1091 | EXPORT_SYMBOL(set_pages_uc); |
| 1078 | 1092 | ||
| 1093 | int set_pages_array_uc(struct page **pages, int addrinarray) | ||
| 1094 | { | ||
| 1095 | unsigned long start; | ||
| 1096 | unsigned long end; | ||
| 1097 | int i; | ||
| 1098 | int free_idx; | ||
| 1099 | |||
| 1100 | for (i = 0; i < addrinarray; i++) { | ||
| 1101 | start = (unsigned long)page_address(pages[i]); | ||
| 1102 | end = start + PAGE_SIZE; | ||
| 1103 | if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL)) | ||
| 1104 | goto err_out; | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | if (cpa_set_pages_array(pages, addrinarray, | ||
| 1108 | __pgprot(_PAGE_CACHE_UC_MINUS)) == 0) { | ||
| 1109 | return 0; /* Success */ | ||
| 1110 | } | ||
| 1111 | err_out: | ||
| 1112 | free_idx = i; | ||
| 1113 | for (i = 0; i < free_idx; i++) { | ||
| 1114 | start = (unsigned long)page_address(pages[i]); | ||
| 1115 | end = start + PAGE_SIZE; | ||
| 1116 | free_memtype(start, end); | ||
| 1117 | } | ||
| 1118 | return -EINVAL; | ||
| 1119 | } | ||
| 1120 | EXPORT_SYMBOL(set_pages_array_uc); | ||
| 1121 | |||
| 1079 | int set_pages_wb(struct page *page, int numpages) | 1122 | int set_pages_wb(struct page *page, int numpages) |
| 1080 | { | 1123 | { |
| 1081 | unsigned long addr = (unsigned long)page_address(page); | 1124 | unsigned long addr = (unsigned long)page_address(page); |
| @@ -1084,6 +1127,26 @@ int set_pages_wb(struct page *page, int numpages) | |||
| 1084 | } | 1127 | } |
| 1085 | EXPORT_SYMBOL(set_pages_wb); | 1128 | EXPORT_SYMBOL(set_pages_wb); |
| 1086 | 1129 | ||
| 1130 | int set_pages_array_wb(struct page **pages, int addrinarray) | ||
| 1131 | { | ||
| 1132 | int retval; | ||
| 1133 | unsigned long start; | ||
| 1134 | unsigned long end; | ||
| 1135 | int i; | ||
| 1136 | |||
| 1137 | retval = cpa_clear_pages_array(pages, addrinarray, | ||
| 1138 | __pgprot(_PAGE_CACHE_MASK)); | ||
| 1139 | |||
| 1140 | for (i = 0; i < addrinarray; i++) { | ||
| 1141 | start = (unsigned long)page_address(pages[i]); | ||
| 1142 | end = start + PAGE_SIZE; | ||
| 1143 | free_memtype(start, end); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | return retval; | ||
| 1147 | } | ||
| 1148 | EXPORT_SYMBOL(set_pages_array_wb); | ||
| 1149 | |||
| 1087 | int set_pages_x(struct page *page, int numpages) | 1150 | int set_pages_x(struct page *page, int numpages) |
| 1088 | { | 1151 | { |
| 1089 | unsigned long addr = (unsigned long)page_address(page); | 1152 | unsigned long addr = (unsigned long)page_address(page); |
