diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 16:47:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 16:47:29 -0400 |
commit | c3b86a29429dac1033e3f602f51fa8d00006a8eb (patch) | |
tree | bcedd0a553ca2396eeb58318ef6ee6b426e83652 /arch/x86/mm/fault.c | |
parent | 8d8d2e9ccd331a1345c88b292ebee9d256fd8749 (diff) | |
parent | 2aeb66d3036dbafc297ac553a257a40283dadb3e (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.c | 43 |
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 | ||
329 | void vmalloc_sync_all(void) | 338 | void 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); |