From patchwork Tue Jan 24 08:49:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 92290 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp1613109qgi; Tue, 24 Jan 2017 00:52:53 -0800 (PST) X-Received: by 10.200.51.134 with SMTP id c6mr27165397qtb.258.1485247973850; Tue, 24 Jan 2017 00:52:53 -0800 (PST) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [65.50.211.133]) by mx.google.com with ESMTPS id s85si12674852qke.158.2017.01.24.00.52.53 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 24 Jan 2017 00:52:53 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 65.50.211.133 as permitted sender) client-ip=65.50.211.133; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 65.50.211.133 as permitted sender) smtp.mailfrom=linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cVwqS-000155-AX; Tue, 24 Jan 2017 08:52:52 +0000 Received: from mail-pg0-f45.google.com ([74.125.83.45]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cVwoh-00007h-VY for linux-arm-kernel@lists.infradead.org; Tue, 24 Jan 2017 08:51:06 +0000 Received: by mail-pg0-f45.google.com with SMTP id 14so53302977pgg.1 for ; Tue, 24 Jan 2017 00:50:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uTpY851nbALPjidZdIGPYUWvIB4M/H4+8tKfm9F3ihY=; b=Nfs2FLTCzEZc9FmCjkzMWFxH+R8tNRa1d8K9UhVOr9nYz5qwMwBOm5IoAo4Ak6Koym OkRcV84VVR327qbrpYiQU/EbrM+7QIQZ5SFmvbJaNqtu1jfos5Nw946a8jYpbxh15mCd 2vy+onhscc7U0JHb+oZV/BuPG/rYNPfv+b+QQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uTpY851nbALPjidZdIGPYUWvIB4M/H4+8tKfm9F3ihY=; b=l6kJTEojdg3/FTwb373oPaNQPR5WWXkmtKVPt55vSEo41wElE46QZJMijcdVTvM8E3 Sl3ZnfbyhUXR2aUymDY5SYIpJ0zJOLYhdmDrAna0642Yo0UlsJafOcWyPV40ekXSJEcD OFENz70i0Ntcnep2PMnD6Q0IQiYXAqqSiiriGYuU6odoAm5o8ugJcGd4aRkguP+EapD7 PpFHY9074th03DGrEOq7cDo9ci8KosDs/3gSYEuOJ/heJRq3CVVO+orUYMzS4rAkVWlM JrHyZyUkTOXvRTnSs3FkvfJvID0K1e407pOxdfeHl25nD9xeVznhOPJsCLDxDmOg5wV+ JqNA== X-Gm-Message-State: AIkVDXJi4R0fqhD7k+nSIUaD56unOSjsk3F6ukTK4p1vx3l9nnOdMxzSxCsdgRbMwhDyfTeg X-Received: by 10.84.179.194 with SMTP id b60mr50265187plc.147.1485247783011; Tue, 24 Jan 2017 00:49:43 -0800 (PST) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id m136sm3596434pga.22.2017.01.24.00.49.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 24 Jan 2017 00:49:42 -0800 (PST) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com Subject: [PATCH v30 04/11] arm64: mm: allow for unmapping memory region from kernel mapping Date: Tue, 24 Jan 2017 17:49:58 +0900 Message-Id: <20170124085004.3892-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170124084638.3770-1-takahiro.akashi@linaro.org> References: <20170124084638.3770-1-takahiro.akashi@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170124_005104_301126_AD67A08A X-CRM114-Status: GOOD ( 16.17 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [74.125.83.45 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [74.125.83.45 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, geoff@infradead.org, kexec@lists.infradead.org, AKASHI Takahiro , james.morse@arm.com, bauerman@linux.vnet.ibm.com, dyoung@redhat.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org The current implementation of create_mapping_late() is only allowed to modify permission attributes (read-only or read-write) against the existing kernel mapping. In this patch, PAGE_KERNEL_INVALID protection attribute is introduced. We will now be able to invalidate (or unmap) some part of the existing kernel mapping by specifying PAGE_KERNEL_INVALID to create_mapping_late(). This feature will be used in a suceeding kdump patch to protect the memory reserved for crash dump kernel once after loaded. Signed-off-by: AKASHI Takahiro --- arch/arm64/include/asm/mmu.h | 2 ++ arch/arm64/include/asm/pgtable-hwdef.h | 2 ++ arch/arm64/include/asm/pgtable-prot.h | 1 + arch/arm64/include/asm/pgtable.h | 4 ++++ arch/arm64/mm/mmu.c | 29 ++++++++++++++++++++--------- 5 files changed, 29 insertions(+), 9 deletions(-) -- 2.11.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 47619411f0ff..a6c1367527bc 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -36,6 +36,8 @@ extern void init_mem_pgprot(void); extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot, bool page_mappings_only); +extern void create_mapping_late(phys_addr_t phys, unsigned long virt, + phys_addr_t size, pgprot_t prot); extern void *fixmap_remap_fdt(phys_addr_t dt_phys); #endif diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index eb0c2bd90de9..e66efec31ca9 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -119,6 +119,7 @@ #define PUD_TABLE_BIT (_AT(pgdval_t, 1) << 1) #define PUD_TYPE_MASK (_AT(pgdval_t, 3) << 0) #define PUD_TYPE_SECT (_AT(pgdval_t, 1) << 0) +#define PUD_VALID PUD_TYPE_SECT /* * Level 2 descriptor (PMD). @@ -128,6 +129,7 @@ #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) #define PMD_TABLE_BIT (_AT(pmdval_t, 1) << 1) +#define PMD_VALID PMD_TYPE_SECT /* * Section diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h index 2142c7726e76..945d84cd5df7 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -54,6 +54,7 @@ #define PAGE_KERNEL_ROX __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY) #define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE) #define PAGE_KERNEL_EXEC_CONT __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT) +#define PAGE_KERNEL_INVALID __pgprot(0) #define PAGE_HYP __pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_HYP_XN) #define PAGE_HYP_EXEC __pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index ffbb9a520563..1904a7c07018 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -364,6 +364,8 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, #define pmd_bad(pmd) (!(pmd_val(pmd) & PMD_TABLE_BIT)) +#define pmd_valid(pmd) (!!(pmd_val(pmd) & PMD_VALID)) + #define pmd_table(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ PMD_TYPE_TABLE) #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ @@ -428,6 +430,7 @@ static inline phys_addr_t pmd_page_paddr(pmd_t pmd) #define pud_none(pud) (!pud_val(pud)) #define pud_bad(pud) (!(pud_val(pud) & PUD_TABLE_BIT)) +#define pud_valid(pud) (!!(pud_val(pud) & PUD_VALID)) #define pud_present(pud) (pud_val(pud)) static inline void set_pud(pud_t *pudp, pud_t pud) @@ -481,6 +484,7 @@ static inline phys_addr_t pud_page_paddr(pud_t pud) #define pgd_none(pgd) (!pgd_val(pgd)) #define pgd_bad(pgd) (!(pgd_val(pgd) & 2)) +#define pgd_valid(pgd) (!!(pgd_val(pgd) & 1)) #define pgd_present(pgd) (pgd_val(pgd)) static inline void set_pgd(pgd_t *pgdp, pgd_t pgd) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 17243e43184e..9c7adcce8e4e 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -133,7 +133,8 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr, * Set the contiguous bit for the subsequent group of PTEs if * its size and alignment are appropriate. */ - if (((addr | PFN_PHYS(pfn)) & ~CONT_PTE_MASK) == 0) { + if ((pgprot_val(prot) & PTE_VALID) && + (((addr | PFN_PHYS(pfn)) & ~CONT_PTE_MASK) == 0)) { if (end - addr >= CONT_PTE_SIZE && !page_mappings_only) __prot = __pgprot(pgprot_val(prot) | PTE_CONT); else @@ -147,7 +148,8 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr, * After the PTE entry has been populated once, we * only allow updates to the permission attributes. */ - BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), pte_val(*pte))); + BUG_ON(pte_valid(old_pte) && pte_valid(*pte) && + !pgattr_change_is_safe(pte_val(old_pte), pte_val(*pte))); } while (pte++, addr += PAGE_SIZE, addr != end); @@ -190,7 +192,8 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, * Set the contiguous bit for the subsequent group of * PMDs if its size and alignment are appropriate. */ - if (((addr | phys) & ~CONT_PMD_MASK) == 0) { + if ((pgprot_val(prot) | PMD_VALID) && + ((addr | phys) & ~CONT_PMD_MASK) == 0) { if (end - addr >= CONT_PMD_SIZE) __prot = __pgprot(pgprot_val(prot) | PTE_CONT); @@ -203,7 +206,8 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end, * After the PMD entry has been populated once, we * only allow updates to the permission attributes. */ - BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd), + BUG_ON(pmd_valid(old_pmd) && pmd_valid(*pmd) && + !pgattr_change_is_safe(pmd_val(old_pmd), pmd_val(*pmd))); } else { alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), @@ -263,7 +267,8 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, * After the PUD entry has been populated once, we * only allow updates to the permission attributes. */ - BUG_ON(!pgattr_change_is_safe(pud_val(old_pud), + BUG_ON(pud_valid(old_pud) && pud_valid(*pud) && + !pgattr_change_is_safe(pud_val(old_pud), pud_val(*pud))); } else { alloc_init_pmd(pud, addr, next, phys, prot, @@ -344,8 +349,8 @@ void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, pgd_pgtable_alloc, page_mappings_only); } -static void create_mapping_late(phys_addr_t phys, unsigned long virt, - phys_addr_t size, pgprot_t prot) +void create_mapping_late(phys_addr_t phys, unsigned long virt, + phys_addr_t size, pgprot_t prot) { if (virt < VMALLOC_START) { pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", @@ -791,14 +796,20 @@ int __init arch_ioremap_pmd_supported(void) int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot) { BUG_ON(phys & ~PUD_MASK); - set_pud(pud, __pud(phys | PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot)))); + set_pud(pud, __pud(phys | + ((pgprot_val(prot) & PUD_VALID) ? + PUD_TYPE_SECT : 0) | + pgprot_val(mk_sect_prot(prot)))); return 1; } int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot) { BUG_ON(phys & ~PMD_MASK); - set_pmd(pmd, __pmd(phys | PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot)))); + set_pmd(pmd, __pmd(phys | + ((pgprot_val(prot) & PMD_VALID) ? + PMD_TYPE_SECT : 0) | + pgprot_val(mk_sect_prot(prot)))); return 1; }