aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/fault.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-21 16:47:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-21 16:47:29 -0400
commitc3b86a29429dac1033e3f602f51fa8d00006a8eb (patch)
treebcedd0a553ca2396eeb58318ef6ee6b426e83652 /arch/x86/mm/fault.c
parent8d8d2e9ccd331a1345c88b292ebee9d256fd8749 (diff)
parent2aeb66d3036dbafc297ac553a257a40283dadb3e (diff)
Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86-32, percpu: Correct the ordering of the percpu readmostly section x86, mm: Enable ARCH_DMA_ADDR_T_64BIT with X86_64 || HIGHMEM64G x86: Spread tlb flush vector between nodes percpu: Introduce a read-mostly percpu API x86, mm: Fix incorrect data type in vmalloc_sync_all() x86, mm: Hold mm->page_table_lock while doing vmalloc_sync x86, mm: Fix bogus whitespace in sync_global_pgds() x86-32: Fix sparse warning for the __PHYSICAL_MASK calculation x86, mm: Add RESERVE_BRK_ARRAY() helper mm, x86: Saving vmcore with non-lazy freeing of vmas x86, kdump: Change copy_oldmem_page() to use cached addressing x86, mm: fix uninitialized addr in kernel_physical_mapping_init() x86, kmemcheck: Remove double test x86, mm: Make spurious_fault check explicitly check the PRESENT bit x86-64, mem: Update all PGDs for direct mapping and vmemmap mapping changes x86, mm: Separate x86_64 vmalloc_sync_all() into separate functions x86, mm: Avoid unnecessary TLB flush
Diffstat (limited to 'arch/x86/mm/fault.c')
-rw-r--r--arch/x86/mm/fault.c43
1 files changed, 18 insertions, 25 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index a24c6cfdccc4..79b0b372d2d0 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -229,7 +229,16 @@ void vmalloc_sync_all(void)
229 229
230 spin_lock_irqsave(&pgd_lock, flags); 230 spin_lock_irqsave(&pgd_lock, flags);
231 list_for_each_entry(page, &pgd_list, lru) { 231 list_for_each_entry(page, &pgd_list, lru) {
232 if (!vmalloc_sync_one(page_address(page), address)) 232 spinlock_t *pgt_lock;
233 pmd_t *ret;
234
235 pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
236
237 spin_lock(pgt_lock);
238 ret = vmalloc_sync_one(page_address(page), address);
239 spin_unlock(pgt_lock);
240
241 if (!ret)
233 break; 242 break;
234 } 243 }
235 spin_unlock_irqrestore(&pgd_lock, flags); 244 spin_unlock_irqrestore(&pgd_lock, flags);
@@ -328,29 +337,7 @@ out:
328 337
329void vmalloc_sync_all(void) 338void vmalloc_sync_all(void)
330{ 339{
331 unsigned long address; 340 sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END);
332
333 for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
334 address += PGDIR_SIZE) {
335
336 const pgd_t *pgd_ref = pgd_offset_k(address);
337 unsigned long flags;
338 struct page *page;
339
340 if (pgd_none(*pgd_ref))
341 continue;
342
343 spin_lock_irqsave(&pgd_lock, flags);
344 list_for_each_entry(page, &pgd_list, lru) {
345 pgd_t *pgd;
346 pgd = (pgd_t *)page_address(page) + pgd_index(address);
347 if (pgd_none(*pgd))
348 set_pgd(pgd, *pgd_ref);
349 else
350 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
351 }
352 spin_unlock_irqrestore(&pgd_lock, flags);
353 }
354} 341}
355 342
356/* 343/*
@@ -898,8 +885,14 @@ spurious_fault(unsigned long error_code, unsigned long address)
898 if (pmd_large(*pmd)) 885 if (pmd_large(*pmd))
899 return spurious_fault_check(error_code, (pte_t *) pmd); 886 return spurious_fault_check(error_code, (pte_t *) pmd);
900 887
888 /*
889 * Note: don't use pte_present() here, since it returns true
890 * if the _PAGE_PROTNONE bit is set. However, this aliases the
891 * _PAGE_GLOBAL bit, which for kernel pages give false positives
892 * when CONFIG_DEBUG_PAGEALLOC is used.
893 */
901 pte = pte_offset_kernel(pmd, address); 894 pte = pte_offset_kernel(pmd, address);
902 if (!pte_present(*pte)) 895 if (!(pte_flags(*pte) & _PAGE_PRESENT))
903 return 0; 896 return 0;
904 897
905 ret = spurious_fault_check(error_code, pte); 898 ret = spurious_fault_check(error_code, pte);