aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2008-03-02 19:17:37 -0500
committerIngo Molnar <mingo@elte.hu>2008-03-03 08:18:27 -0500
commit9b5cf48b06a52c04b85c88642c3b620db8e1d592 (patch)
tree1cb87d4778bbac056a4abdde770555ea5f3221a2 /arch/x86
parent038f2f725503b55ab76cfd2645915a85594710fe (diff)
x86: revert "x86: CPA: avoid split of alias mappings"
Revert: commit 8be8f54bae3453588011cad06363813a5293af53 Author: Thomas Gleixner <tglx@linutronix.de> Date: Sat Feb 23 20:43:21 2008 +0100 x86: CPA: avoid split of alias mappings because it clearly mishandles the case when __change_page_attr(), called from __change_page_attr_set_clr(), changes cpa->processed to 1 and cpa_process_alias(cpa) is executed right after that. This crashes my x86-64 test box early in the boot process (ref. http://bugzilla.kernel.org/show_bug.cgi?id=10140#c4). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/mm/pageattr.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 7049294fb469..14e48b5a94ba 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -26,7 +26,6 @@ struct cpa_data {
26 pgprot_t mask_set; 26 pgprot_t mask_set;
27 pgprot_t mask_clr; 27 pgprot_t mask_clr;
28 int numpages; 28 int numpages;
29 int processed;
30 int flushtlb; 29 int flushtlb;
31 unsigned long pfn; 30 unsigned long pfn;
32}; 31};
@@ -291,8 +290,8 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
291 */ 290 */
292 nextpage_addr = (address + psize) & pmask; 291 nextpage_addr = (address + psize) & pmask;
293 numpages = (nextpage_addr - address) >> PAGE_SHIFT; 292 numpages = (nextpage_addr - address) >> PAGE_SHIFT;
294 if (numpages < cpa->processed) 293 if (numpages < cpa->numpages)
295 cpa->processed = numpages; 294 cpa->numpages = numpages;
296 295
297 /* 296 /*
298 * We are safe now. Check whether the new pgprot is the same: 297 * We are safe now. Check whether the new pgprot is the same:
@@ -319,7 +318,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
319 */ 318 */
320 addr = address + PAGE_SIZE; 319 addr = address + PAGE_SIZE;
321 pfn++; 320 pfn++;
322 for (i = 1; i < cpa->processed; i++, addr += PAGE_SIZE, pfn++) { 321 for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE, pfn++) {
323 pgprot_t chk_prot = static_protections(new_prot, addr, pfn); 322 pgprot_t chk_prot = static_protections(new_prot, addr, pfn);
324 323
325 if (pgprot_val(chk_prot) != pgprot_val(new_prot)) 324 if (pgprot_val(chk_prot) != pgprot_val(new_prot))
@@ -343,7 +342,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
343 * that we limited the number of possible pages already to 342 * that we limited the number of possible pages already to
344 * the number of pages in the large page. 343 * the number of pages in the large page.
345 */ 344 */
346 if (address == (nextpage_addr - psize) && cpa->processed == numpages) { 345 if (address == (nextpage_addr - psize) && cpa->numpages == numpages) {
347 /* 346 /*
348 * The address is aligned and the number of pages 347 * The address is aligned and the number of pages
349 * covers the full page. 348 * covers the full page.
@@ -573,7 +572,7 @@ repeat:
573 set_pte_atomic(kpte, new_pte); 572 set_pte_atomic(kpte, new_pte);
574 cpa->flushtlb = 1; 573 cpa->flushtlb = 1;
575 } 574 }
576 cpa->processed = 1; 575 cpa->numpages = 1;
577 return 0; 576 return 0;
578 } 577 }
579 578
@@ -584,7 +583,7 @@ repeat:
584 do_split = try_preserve_large_page(kpte, address, cpa); 583 do_split = try_preserve_large_page(kpte, address, cpa);
585 /* 584 /*
586 * When the range fits into the existing large page, 585 * When the range fits into the existing large page,
587 * return. cp->processed and cpa->tlbflush have been updated in 586 * return. cp->numpages and cpa->tlbflush have been updated in
588 * try_large_page: 587 * try_large_page:
589 */ 588 */
590 if (do_split <= 0) 589 if (do_split <= 0)
@@ -663,7 +662,7 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
663 * Store the remaining nr of pages for the large page 662 * Store the remaining nr of pages for the large page
664 * preservation check. 663 * preservation check.
665 */ 664 */
666 cpa->numpages = cpa->processed = numpages; 665 cpa->numpages = numpages;
667 666
668 ret = __change_page_attr(cpa, checkalias); 667 ret = __change_page_attr(cpa, checkalias);
669 if (ret) 668 if (ret)
@@ -680,9 +679,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
680 * CPA operation. Either a large page has been 679 * CPA operation. Either a large page has been
681 * preserved or a single page update happened. 680 * preserved or a single page update happened.
682 */ 681 */
683 BUG_ON(cpa->processed > numpages); 682 BUG_ON(cpa->numpages > numpages);
684 numpages -= cpa->processed; 683 numpages -= cpa->numpages;
685 cpa->vaddr += cpa->processed * PAGE_SIZE; 684 cpa->vaddr += cpa->numpages * PAGE_SIZE;
686 } 685 }
687 return 0; 686 return 0;
688} 687}