diff options
Diffstat (limited to 'arch/x86_64/mm/pageattr.c')
-rw-r--r-- | arch/x86_64/mm/pageattr.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c index 081409aa3452..d653d0bf3df6 100644 --- a/arch/x86_64/mm/pageattr.c +++ b/arch/x86_64/mm/pageattr.c | |||
@@ -180,16 +180,24 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, | |||
180 | */ | 180 | */ |
181 | int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot) | 181 | int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot) |
182 | { | 182 | { |
183 | int err = 0; | 183 | int err = 0, kernel_map = 0; |
184 | int i; | 184 | int i; |
185 | 185 | ||
186 | if (address >= __START_KERNEL_map | ||
187 | && address < __START_KERNEL_map + KERNEL_TEXT_SIZE) { | ||
188 | address = (unsigned long)__va(__pa(address)); | ||
189 | kernel_map = 1; | ||
190 | } | ||
191 | |||
186 | down_write(&init_mm.mmap_sem); | 192 | down_write(&init_mm.mmap_sem); |
187 | for (i = 0; i < numpages; i++, address += PAGE_SIZE) { | 193 | for (i = 0; i < numpages; i++, address += PAGE_SIZE) { |
188 | unsigned long pfn = __pa(address) >> PAGE_SHIFT; | 194 | unsigned long pfn = __pa(address) >> PAGE_SHIFT; |
189 | 195 | ||
190 | err = __change_page_attr(address, pfn, prot, PAGE_KERNEL); | 196 | if (!kernel_map || pte_present(pfn_pte(0, prot))) { |
191 | if (err) | 197 | err = __change_page_attr(address, pfn, prot, PAGE_KERNEL); |
192 | break; | 198 | if (err) |
199 | break; | ||
200 | } | ||
193 | /* Handle kernel mapping too which aliases part of the | 201 | /* Handle kernel mapping too which aliases part of the |
194 | * lowmem */ | 202 | * lowmem */ |
195 | if (__pa(address) < KERNEL_TEXT_SIZE) { | 203 | if (__pa(address) < KERNEL_TEXT_SIZE) { |