diff options
author | venkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com> | 2009-03-19 17:51:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-20 05:34:49 -0400 |
commit | 0f3507555f6fa4acbc85a646d6e8766230db38fc (patch) | |
tree | f46d34e37e141c9bc305f5c8c8835fa6cd0797fb | |
parent | 9ae2847591c857bed44bc094b908b412bfa1b244 (diff) |
x86, CPA: Add set_pages_arrayuc and set_pages_array_wb
Add new interfaces:
set_pages_array_uc()
set_pages_array_wb()
that can be used change the page attribute for a bunch of pages with
flush etc done once at the end of all the changes. These interfaces
are similar to existing set_memory_array_uc() and set_memory_array_wc().
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: arjan@infradead.org
Cc: eric@anholt.net
Cc: airlied@redhat.com
LKML-Reference: <20090319215358.901545000@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-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); |