diff options
Diffstat (limited to 'arch/x86/mm')
| -rw-r--r-- | arch/x86/mm/fault.c | 6 | ||||
| -rw-r--r-- | arch/x86/mm/pageattr-test.c | 2 | ||||
| -rw-r--r-- | arch/x86/mm/pageattr.c | 12 | ||||
| -rw-r--r-- | arch/x86/mm/pgtable.c | 7 |
4 files changed, 19 insertions, 8 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 2b97525246d4..0e883364abb5 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -378,10 +378,12 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) | |||
| 378 | if (pgd_none(*pgd_ref)) | 378 | if (pgd_none(*pgd_ref)) |
| 379 | return -1; | 379 | return -1; |
| 380 | 380 | ||
| 381 | if (pgd_none(*pgd)) | 381 | if (pgd_none(*pgd)) { |
| 382 | set_pgd(pgd, *pgd_ref); | 382 | set_pgd(pgd, *pgd_ref); |
| 383 | else | 383 | arch_flush_lazy_mmu_mode(); |
| 384 | } else { | ||
| 384 | BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); | 385 | BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); |
| 386 | } | ||
| 385 | 387 | ||
| 386 | /* | 388 | /* |
| 387 | * Below here mismatches are bugs because these lower tables | 389 | * Below here mismatches are bugs because these lower tables |
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c index b0086567271c..0e38951e65eb 100644 --- a/arch/x86/mm/pageattr-test.c +++ b/arch/x86/mm/pageattr-test.c | |||
| @@ -68,7 +68,7 @@ static int print_split(struct split_state *s) | |||
| 68 | s->gpg++; | 68 | s->gpg++; |
| 69 | i += GPS/PAGE_SIZE; | 69 | i += GPS/PAGE_SIZE; |
| 70 | } else if (level == PG_LEVEL_2M) { | 70 | } else if (level == PG_LEVEL_2M) { |
| 71 | if (!(pte_val(*pte) & _PAGE_PSE)) { | 71 | if ((pte_val(*pte) & _PAGE_PRESENT) && !(pte_val(*pte) & _PAGE_PSE)) { |
| 72 | printk(KERN_ERR | 72 | printk(KERN_ERR |
| 73 | "%lx level %d but not PSE %Lx\n", | 73 | "%lx level %d but not PSE %Lx\n", |
| 74 | addr, level, (u64)pte_val(*pte)); | 74 | addr, level, (u64)pte_val(*pte)); |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 091934e1d0d9..fb4e73ec24d8 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
| @@ -467,7 +467,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
| 467 | * We are safe now. Check whether the new pgprot is the same: | 467 | * We are safe now. Check whether the new pgprot is the same: |
| 468 | */ | 468 | */ |
| 469 | old_pte = *kpte; | 469 | old_pte = *kpte; |
| 470 | old_prot = new_prot = req_prot = pte_pgprot(old_pte); | 470 | old_prot = req_prot = pte_pgprot(old_pte); |
| 471 | 471 | ||
| 472 | pgprot_val(req_prot) &= ~pgprot_val(cpa->mask_clr); | 472 | pgprot_val(req_prot) &= ~pgprot_val(cpa->mask_clr); |
| 473 | pgprot_val(req_prot) |= pgprot_val(cpa->mask_set); | 473 | pgprot_val(req_prot) |= pgprot_val(cpa->mask_set); |
| @@ -478,12 +478,12 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
| 478 | * a non present pmd. The canon_pgprot will clear _PAGE_GLOBAL | 478 | * a non present pmd. The canon_pgprot will clear _PAGE_GLOBAL |
| 479 | * for the ancient hardware that doesn't support it. | 479 | * for the ancient hardware that doesn't support it. |
| 480 | */ | 480 | */ |
| 481 | if (pgprot_val(new_prot) & _PAGE_PRESENT) | 481 | if (pgprot_val(req_prot) & _PAGE_PRESENT) |
| 482 | pgprot_val(new_prot) |= _PAGE_PSE | _PAGE_GLOBAL; | 482 | pgprot_val(req_prot) |= _PAGE_PSE | _PAGE_GLOBAL; |
| 483 | else | 483 | else |
| 484 | pgprot_val(new_prot) &= ~(_PAGE_PSE | _PAGE_GLOBAL); | 484 | pgprot_val(req_prot) &= ~(_PAGE_PSE | _PAGE_GLOBAL); |
| 485 | 485 | ||
| 486 | new_prot = canon_pgprot(new_prot); | 486 | req_prot = canon_pgprot(req_prot); |
| 487 | 487 | ||
| 488 | /* | 488 | /* |
| 489 | * old_pte points to the large page base address. So we need | 489 | * old_pte points to the large page base address. So we need |
| @@ -1413,6 +1413,8 @@ void kernel_map_pages(struct page *page, int numpages, int enable) | |||
| 1413 | * but that can deadlock->flush only current cpu: | 1413 | * but that can deadlock->flush only current cpu: |
| 1414 | */ | 1414 | */ |
| 1415 | __flush_tlb_all(); | 1415 | __flush_tlb_all(); |
| 1416 | |||
| 1417 | arch_flush_lazy_mmu_mode(); | ||
| 1416 | } | 1418 | } |
| 1417 | 1419 | ||
| 1418 | #ifdef CONFIG_HIBERNATION | 1420 | #ifdef CONFIG_HIBERNATION |
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 193350b51f90..17fda6a8b3c2 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c | |||
| @@ -58,6 +58,13 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte) | |||
| 58 | void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd) | 58 | void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd) |
| 59 | { | 59 | { |
| 60 | paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT); | 60 | paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT); |
| 61 | /* | ||
| 62 | * NOTE! For PAE, any changes to the top page-directory-pointer-table | ||
| 63 | * entries need a full cr3 reload to flush. | ||
| 64 | */ | ||
| 65 | #ifdef CONFIG_X86_PAE | ||
| 66 | tlb->need_flush_all = 1; | ||
| 67 | #endif | ||
| 61 | tlb_remove_page(tlb, virt_to_page(pmd)); | 68 | tlb_remove_page(tlb, virt_to_page(pmd)); |
| 62 | } | 69 | } |
| 63 | 70 | ||
