diff options
| author | Greg Kroah-Hartman <gregkh@google.com> | 2018-08-17 21:25:15 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@google.com> | 2018-08-17 21:25:15 +0200 |
| commit | f76bdbdd516da14916d9eb723bb5fa16aacf6284 (patch) | |
| tree | 7f7d5318c1f895b6e0c96e7a2bc6cd8f657305e5 /arch/x86/mm/pgtable.c | |
| parent | f057ff937754efc42d56bee825187b2ce6c36958 (diff) | |
| parent | 45cf1802a1057650768430cf3168ff7a02163338 (diff) | |
Merge 4.4.149 into android-4.4
Changes in 4.4.149
x86/mm: Disable ioremap free page handling on x86-PAE
tcp: Fix missing range_truesize enlargement in the backport
kasan: don't emit builtin calls when sanitization is off
i2c: ismt: fix wrong device address when unmap the data buffer
kbuild: verify that $DEPMOD is installed
crypto: vmac - require a block cipher with 128-bit block size
crypto: vmac - separate tfm and request context
crypto: blkcipher - fix crash flushing dcache in error path
crypto: ablkcipher - fix crash flushing dcache in error path
ASoC: Intel: cht_bsw_max98090_ti: Fix jack initialization
Bluetooth: hidp: buffer overflow in hidp_process_report
ioremap: Update pgtable free interfaces with addr
x86/mm: Add TLB purge to free pmd/pte page interfaces
Linux 4.4.149
Change-Id: I1e23095dd229992359341bda5c05e9b5b59fec45
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'arch/x86/mm/pgtable.c')
| -rw-r--r-- | arch/x86/mm/pgtable.c | 61 |
1 files changed, 53 insertions, 8 deletions
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 08e94b6139ab..55c7446311a7 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -676,28 +676,50 @@ int pmd_clear_huge(pmd_t *pmd) return 0; } +#ifdef CONFIG_X86_64 /** * pud_free_pmd_page - Clear pud entry and free pmd page. * @pud: Pointer to a PUD. + * @addr: Virtual address associated with pud. * - * Context: The pud range has been unmaped and TLB purged. + * Context: The pud range has been unmapped and TLB purged. * Return: 1 if clearing the entry succeeded. 0 otherwise. + * + * NOTE: Callers must allow a single page allocation. */ -int pud_free_pmd_page(pud_t *pud) +int pud_free_pmd_page(pud_t *pud, unsigned long addr) { - pmd_t *pmd; + pmd_t *pmd, *pmd_sv; + pte_t *pte; int i; if (pud_none(*pud)) return 1; pmd = (pmd_t *)pud_page_vaddr(*pud); + pmd_sv = (pmd_t *)__get_free_page(GFP_KERNEL); + if (!pmd_sv) + return 0; - for (i = 0; i < PTRS_PER_PMD; i++) - if (!pmd_free_pte_page(&pmd[i])) - return 0; + for (i = 0; i < PTRS_PER_PMD; i++) { + pmd_sv[i] = pmd[i]; + if (!pmd_none(pmd[i])) + pmd_clear(&pmd[i]); + } pud_clear(pud); + + /* INVLPG to clear all paging-structure caches */ + flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1); + + for (i = 0; i < PTRS_PER_PMD; i++) { + if (!pmd_none(pmd_sv[i])) { + pte = (pte_t *)pmd_page_vaddr(pmd_sv[i]); + free_page((unsigned long)pte); + } + } + + free_page((unsigned long)pmd_sv); free_page((unsigned long)pmd); return 1; @@ -706,11 +728,12 @@ int pud_free_pmd_page(pud_t *pud) /** * pmd_free_pte_page - Clear pmd entry and free pte page. * @pmd: Pointer to a PMD. + * @addr: Virtual address associated with pmd. * - * Context: The pmd range has been unmaped and TLB purged. + * Context: The pmd range has been unmapped and TLB purged. * Return: 1 if clearing the entry succeeded. 0 otherwise. */ -int pmd_free_pte_page(pmd_t *pmd) +int pmd_free_pte_page(pmd_t *pmd, unsigned long addr) { pte_t *pte; @@ -719,8 +742,30 @@ int pmd_free_pte_page(pmd_t *pmd) pte = (pte_t *)pmd_page_vaddr(*pmd); pmd_clear(pmd); + + /* INVLPG to clear all paging-structure caches */ + flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1); + free_page((unsigned long)pte); return 1; } + +#else /* !CONFIG_X86_64 */ + +int pud_free_pmd_page(pud_t *pud, unsigned long addr) +{ + return pud_none(*pud); +} + +/* + * Disable free page handling on x86-PAE. This assures that ioremap() + * does not update sync'd pmd entries. See vmalloc_sync_one(). + */ +int pmd_free_pte_page(pmd_t *pmd, unsigned long addr) +{ + return pmd_none(*pmd); +} + +#endif /* CONFIG_X86_64 */ #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ |
