All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Morse <james.morse@arm.com>
To: Pavel Tatashin <pasha.tatashin@soleen.com>
Cc: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH 2/3] arm64: hibernate: Split create_safe_exec_page() and its mapping code
Date: Wed, 15 Jan 2020 14:33:21 +0000	[thread overview]
Message-ID: <20200115143322.214247-3-james.morse@arm.com> (raw)
In-Reply-To: <20200115143322.214247-1-james.morse@arm.com>

Kexec wants to share hibernate's page table setup code, but needs its
memory-copy buffer idmapped as it also has to turn the MMU off.

Split the copy of this buffer from the code that maps it.

Signed-off-by: James Morse <james.morse@arm.com>
---
 arch/arm64/kernel/hibernate.c | 57 +++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 23 deletions(-)

diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index a96b2921d22c..7f8cb7596f9e 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -183,19 +183,9 @@ int arch_hibernation_header_restore(void *addr)
 EXPORT_SYMBOL(arch_hibernation_header_restore);
 
 /*
- * Copies length bytes, starting at src_start into an new page,
- * perform cache maintentance, then maps it at the specified address low
- * address as executable.
- *
- * This is used by hibernate to copy the code it needs to execute when
- * overwriting the kernel text. This function generates a new set of page
- * tables, which it loads into ttbr0.
- *
- * Length is provided as we probably only want 4K of data, even on a 64K
- * page system.
+ * Create a set of page tables that map page to dst_addr.
  */
-static int create_safe_exec_page(void *src_start, size_t length,
-				 unsigned long dst_addr,
+static int create_single_mapping(unsigned long page, unsigned long dst_addr,
 				 phys_addr_t *phys_dst_addr,
 				 void *(*allocator)(gfp_t mask),
 				 gfp_t mask)
@@ -206,15 +196,6 @@ static int create_safe_exec_page(void *src_start, size_t length,
 	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
-	unsigned long dst = (unsigned long)allocator(mask);
-
-	if (!dst) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	memcpy((void *)dst, src_start, length);
-	__flush_icache_range(dst, dst + length);
 
 	trans_pgd = allocator(mask);
 	if (!trans_pgd) {
@@ -253,7 +234,7 @@ static int create_safe_exec_page(void *src_start, size_t length,
 	}
 
 	ptep = pte_offset_kernel(pmdp, dst_addr);
-	set_pte(ptep, pfn_pte(virt_to_pfn(dst), PAGE_KERNEL_EXEC));
+	set_pte(ptep, pfn_pte(virt_to_pfn(page), PAGE_KERNEL_EXEC));
 
 	/*
 	 * Load our new page tables. A strict BBM approach requires that we
@@ -272,12 +253,42 @@ static int create_safe_exec_page(void *src_start, size_t length,
 	write_sysreg(phys_to_ttbr(virt_to_phys(pgdp)), ttbr0_el1);
 	isb();
 
-	*phys_dst_addr = virt_to_phys((void *)dst);
+	*phys_dst_addr = virt_to_phys((void *)page);
 
 out:
 	return rc;
 }
 
+/*
+ * Copies length bytes, starting at src_start into an new page,
+ * perform cache maintentance, then maps it at the specified address low
+ * address as executable.
+ *
+ * This is used by hibernate to copy the code it needs to execute when
+ * overwriting the kernel text. This function generates a new set of page
+ * tables, which it loads into ttbr0.
+ *
+ * Length is provided as we probably only want 4K of data, even on a 64K
+ * page system.
+ */
+static int create_safe_exec_page(void *src_start, size_t length,
+				 unsigned long dst_addr,
+				 phys_addr_t *phys_dst_addr,
+				 void *(*allocator)(gfp_t mask),
+				 gfp_t mask)
+{
+	unsigned long page = (unsigned long)allocator(mask);
+
+	if (!page)
+		return -ENOMEM;
+
+	memcpy((void *)page, src_start, length);
+	__flush_icache_range(page, page + length);
+
+	return create_single_mapping(page, dst_addr, phys_dst_addr,
+				     allocator, gfp_t mask)
+}
+
 #define dcache_clean_range(start, end)	__flush_dcache_area(start, (end - start))
 
 int swsusp_arch_suspend(void)
-- 
2.24.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2020-01-15 14:34 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-15 14:33 [RFC PATCH 0/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse
2020-01-15 14:33 ` [RFC PATCH 1/3] arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz() James Morse
2020-01-15 14:33 ` James Morse [this message]
2020-01-15 14:33 ` [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse
2020-03-20 21:22   ` Pavel Tatashin
2020-03-25  9:58     ` James Morse
2020-03-25 13:29       ` Pavel Tatashin
2020-03-25 13:41         ` Pavel Tatashin
2020-03-25 17:08         ` James Morse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200115143322.214247-3-james.morse@arm.com \
    --to=james.morse@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=pasha.tatashin@soleen.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.