From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934442AbdC3Qj6 (ORCPT ); Thu, 30 Mar 2017 12:39:58 -0400 Received: from foss.arm.com ([217.140.101.70]:50004 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933175AbdC3Qj4 (ORCPT ); Thu, 30 Mar 2017 12:39:56 -0400 From: Punit Agrawal To: catalin.marinas@arm.com, will.deacon@arm.com, akpm@linux-foundation.org Cc: Punit Agrawal , linux-mm@kvack.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, tbaicar@codeaurora.org, kirill.shutemov@linux.intel.com, mike.kravetz@oracle.com, David Woods Subject: [PATCH 2/4] arm64: hugetlbpages: Correctly handle swap entries in huge_pte_offset() Date: Thu, 30 Mar 2017 17:38:47 +0100 Message-Id: <20170330163849.18402-3-punit.agrawal@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170330163849.18402-1-punit.agrawal@arm.com> References: <20170330163849.18402-1-punit.agrawal@arm.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org huge_pte_offset() does not correctly handle poisoned or migration page table entries. Not knowing the size of the hugepage entry being requested only compounded the problem. The recently added hstate parameter can be used to determine the size of hugepage being accessed. Use the size to find the correct page table entry to return when coming across a swap page table entry. Signed-off-by: Punit Agrawal Cc: David Woods --- arch/arm64/mm/hugetlbpage.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 9ca742c4c1ab..44014403081f 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -192,38 +192,39 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, struct hstate *h) { + unsigned long sz = huge_page_size(h); pgd_t *pgd; pud_t *pud; - pmd_t *pmd = NULL; - pte_t *pte = NULL; + pmd_t *pmd; + pte_t *pte; pgd = pgd_offset(mm, addr); pr_debug("%s: addr:0x%lx pgd:%p\n", __func__, addr, pgd); if (!pgd_present(*pgd)) return NULL; + pud = pud_offset(pgd, addr); - if (!pud_present(*pud)) + if (pud_none(*pud) && sz != PUD_SIZE) return NULL; - - if (pud_huge(*pud)) + else if (!pud_table(*pud)) return (pte_t *)pud; + + if (sz == CONT_PMD_SIZE) + addr &= CONT_PMD_MASK; + pmd = pmd_offset(pud, addr); - if (!pmd_present(*pmd)) + if (pmd_none(*pmd) && + !(sz == PMD_SIZE || sz == CONT_PMD_SIZE)) return NULL; - - if (pte_cont(pmd_pte(*pmd))) { - pmd = pmd_offset( - pud, (addr & CONT_PMD_MASK)); - return (pte_t *)pmd; - } - if (pmd_huge(*pmd)) + else if (!pmd_table(*pmd)) return (pte_t *)pmd; - pte = pte_offset_kernel(pmd, addr); - if (pte_present(*pte) && pte_cont(*pte)) { + + if (sz == CONT_PTE_SIZE) { pte = pte_offset_kernel( pmd, (addr & CONT_PTE_MASK)); return pte; } + return NULL; } -- 2.11.0