All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, Peter Zijlstra <peterz@infradead.org>,
	Bin Yang <bin.yang@intel.com>,
	Dave Hansen <dave.hansen@intel.com>,
	Mark Gross <mark.gross@intel.com>
Subject: [patch V3 04/11] x86/mm/cpa: Allow range check for static protections
Date: Mon, 17 Sep 2018 16:29:10 +0200	[thread overview]
Message-ID: <20180917143545.995734490@linutronix.de> (raw)
In-Reply-To: 20180917142906.384767038@linutronix.de

[-- Attachment #1: x86-mm-cpa--Allow-range-check-for-static-protections.patch --]
[-- Type: text/plain, Size: 6307 bytes --]

Checking static protections only page by page is slow especially for huge
pages. To allow quick checks over a complete range, add the ability to do
that.

Make the checks inclusive so the ranges can be directly used for debug output
later.

No functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/mm/pageattr.c |   69 +++++++++++++++++++++++++++++++------------------
 1 file changed, 44 insertions(+), 25 deletions(-)

--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -286,22 +286,29 @@ static void cpa_flush_array(unsigned lon
 	}
 }
 
+static bool overlaps(unsigned long r1_start, unsigned long r1_end,
+		     unsigned long r2_start, unsigned long r2_end)
+{
+	return (r1_start <= r2_end && r1_end >= r2_start) ||
+		(r2_start <= r1_end && r2_end >= r1_start);
+}
+
 #ifdef CONFIG_PCI_BIOS
 /*
  * The BIOS area between 640k and 1Mb needs to be executable for PCI BIOS
  * based config access (CONFIG_PCI_GOBIOS) support.
  */
 #define BIOS_PFN	PFN_DOWN(BIOS_BEGIN)
-#define BIOS_PFN_END	PFN_DOWN(BIOS_END)
+#define BIOS_PFN_END	PFN_DOWN(BIOS_END - 1)
 
-static pgprotval_t protect_pci_bios(unsigned long pfn)
+static pgprotval_t protect_pci_bios(unsigned long spfn, unsigned long epfn)
 {
-	if (pcibios_enabled && within(pfn, BIOS_PFN, BIOS_PFN_END))
+	if (pcibios_enabled && overlaps(spfn, epfn, BIOS_PFN, BIOS_PFN_END))
 		return _PAGE_NX;
 	return 0;
 }
 #else
-static pgprotval_t protect_pci_bios(unsigned long pfn)
+static pgprotval_t protect_pci_bios(unsigned long spfn, unsigned long epfn)
 {
 	return 0;
 }
@@ -312,12 +319,17 @@ static pgprotval_t protect_pci_bios(unsi
  * aliases.  This also includes __ro_after_init, so do not enforce until
  * kernel_set_to_readonly is true.
  */
-static pgprotval_t protect_rodata(unsigned long pfn)
+static pgprotval_t protect_rodata(unsigned long spfn, unsigned long epfn)
 {
-	unsigned long start_pfn = __pa_symbol(__start_rodata) >> PAGE_SHIFT;
-	unsigned long end_pfn = __pa_symbol(__end_rodata) >> PAGE_SHIFT;
+	unsigned long epfn_ro, spfn_ro = PFN_DOWN(__pa_symbol(__start_rodata));
+
+	/*
+	 * Note: __end_rodata is at page aligned and not inclusive, so
+	 * subtract 1 to get the last enforced PFN in the rodata area.
+	 */
+	epfn_ro = PFN_DOWN(__pa_symbol(__end_rodata)) - 1;
 
-	if (kernel_set_to_readonly && within(pfn, start_pfn, end_pfn))
+	if (kernel_set_to_readonly && overlaps(spfn, epfn, spfn_ro, epfn_ro))
 		return _PAGE_RW;
 	return 0;
 }
@@ -327,9 +339,12 @@ static pgprotval_t protect_rodata(unsign
  * not cover __inittext since that is gone after boot. On 64bit we do not
  * enforce !NX on the low mapping
  */
-static pgprotval_t protect_kernel_text(unsigned long address)
+static pgprotval_t protect_kernel_text(unsigned long start, unsigned long end)
 {
-	if (within(address, (unsigned long)_text, (unsigned long)_etext))
+	unsigned long t_end = (unsigned long)_etext - 1;
+	unsigned long t_start = (unsigned long)_text;
+
+	if (overlaps(start, end, t_start, t_end))
 		return _PAGE_NX;
 	return 0;
 }
@@ -344,13 +359,14 @@ static pgprotval_t protect_kernel_text(u
  * This will preserve the large page mappings for kernel text/data at no
  * extra cost.
  */
-static pgprotval_t protect_kernel_text_ro(unsigned long address)
+static pgprotval_t protect_kernel_text_ro(unsigned long start,
+					  unsigned long end)
 {
-	unsigned long end = (unsigned long)__end_rodata_hpage_align;
-	unsigned long start = (unsigned long)_text;
+	unsigned long t_end = (unsigned long)__end_rodata_hpage_align - 1;
+	unsigned long t_start = (unsigned long)_text;
 	unsigned int level;
 
-	if (!kernel_set_to_readonly || !within(address, start, end))
+	if (!kernel_set_to_readonly || !overlaps(start, end, t_start, t_end))
 		return 0;
 	/*
 	 * Don't enforce the !RW mapping for the kernel text mapping, if
@@ -364,12 +380,13 @@ static pgprotval_t protect_kernel_text_r
 	 * so the protections for kernel text and identity mappings have to
 	 * be the same.
 	 */
-	if (lookup_address(address, &level) && (level != PG_LEVEL_4K))
+	if (lookup_address(start, &level) && (level != PG_LEVEL_4K))
 		return _PAGE_RW;
 	return 0;
 }
 #else
-static pgprotval_t protect_kernel_text_ro(unsigned long address)
+static pgprotval_t protect_kernel_text_ro(unsigned long start,
+					  unsigned long end)
 {
 	return 0;
 }
@@ -381,18 +398,20 @@ static pgprotval_t protect_kernel_text_r
  * right (again, ioremap() on BIOS memory is not uncommon) so this function
  * checks and fixes these known static required protection bits.
  */
-static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
-					  unsigned long pfn)
+static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
+					  unsigned long pfn, unsigned long npg)
 {
 	pgprotval_t forbidden;
+	unsigned long end;
 
 	/* Operate on the virtual address */
-	forbidden  = protect_kernel_text(address);
-	forbidden |= protect_kernel_text_ro(address);
+	end = start + npg * PAGE_SIZE - 1;
+	forbidden  = protect_kernel_text(start, end);
+	forbidden |= protect_kernel_text_ro(start, end);
 
 	/* Check the PFN directly */
-	forbidden |= protect_pci_bios(pfn);
-	forbidden |= protect_rodata(pfn);
+	forbidden |= protect_pci_bios(pfn, pfn + npg - 1);
+	forbidden |= protect_rodata(pfn, pfn + npg - 1);
 
 	return __pgprot(pgprot_val(prot) & ~forbidden);
 }
@@ -664,10 +683,10 @@ static int __should_split_large_page(pte
 	 * in it results in a different pgprot than the first one of the
 	 * requested range. If yes, then the page needs to be split.
 	 */
-	new_prot = static_protections(req_prot, address, pfn);
+	new_prot = static_protections(req_prot, address, pfn, 1);
 	pfn = old_pfn;
 	for (i = 0, addr = lpaddr; i < numpages; i++, addr += PAGE_SIZE, pfn++) {
-		pgprot_t chk_prot = static_protections(req_prot, addr, pfn);
+		pgprot_t chk_prot = static_protections(req_prot, addr, pfn, 1);
 
 		if (pgprot_val(chk_prot) != pgprot_val(new_prot))
 			return 1;
@@ -1277,7 +1296,7 @@ static int __change_page_attr(struct cpa
 		pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
 		pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
 
-		new_prot = static_protections(new_prot, address, pfn);
+		new_prot = static_protections(new_prot, address, pfn, 1);
 
 		new_prot = pgprot_clear_protnone_bits(new_prot);
 



  parent reply	other threads:[~2018-09-17 14:38 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-17 14:29 [patch V3 00/11] x86/mm/cpa: Improve large page preservation handling Thomas Gleixner
2018-09-17 14:29 ` [patch V3 01/11] x86/mm/init32: Mark text and rodata RO in one go Thomas Gleixner
2018-09-21 16:15   ` Dave Hansen
2018-09-27 18:45   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 02/11] x86/mm/cpa: Split, rename and clean up try_preserve_large_page() Thomas Gleixner
2018-09-18  7:03   ` Peter Zijlstra
2018-09-18  8:19   ` Peter Zijlstra
2018-09-18 12:14     ` Peter Zijlstra
2018-09-18 22:34       ` Thomas Gleixner
2018-09-21 16:22   ` Dave Hansen
2018-09-27 18:46   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 03/11] x86/mm/cpa: Rework static_protections() Thomas Gleixner
2018-09-21 16:33   ` Dave Hansen
2018-09-27 18:46   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` Thomas Gleixner [this message]
2018-09-21 16:36   ` [patch V3 04/11] x86/mm/cpa: Allow range check for static protections Dave Hansen
2018-09-27 18:47   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 05/11] x86/mm/cpa: Add debug mechanism Thomas Gleixner
2018-09-21 16:40   ` Dave Hansen
2018-09-22 10:33     ` Peter Zijlstra
2018-09-27 18:48   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 06/11] x86/mm/cpa: Add large page preservation statistics Thomas Gleixner
2018-09-21 19:59   ` Dave Hansen
2018-09-27 18:48   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 07/11] x86/mm/cpa: Avoid static protection checks on unmap Thomas Gleixner
2018-09-21 20:01   ` Dave Hansen
2018-09-27 18:49   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 08/11] x86/mm/cpa: Add sanity check for existing mappings Thomas Gleixner
2018-09-18  7:14   ` Peter Zijlstra
2018-09-21 20:07   ` Dave Hansen
2018-09-27 18:49   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 09/11] x86/mm/cpa: Optimize same protection check Thomas Gleixner
2018-09-21 20:12   ` Dave Hansen
2018-09-27 18:07     ` Thomas Gleixner
2018-09-27 18:50   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 10/11] x86/mm/cpa: Do the range check early Thomas Gleixner
2018-09-21 20:26   ` Dave Hansen
2018-09-27 18:50   ` [tip:x86/mm] " tip-bot for Thomas Gleixner
2018-09-17 14:29 ` [patch V3 11/11] x86/mm/cpa: Avoid the 4k pages check completely Thomas Gleixner
2018-09-21 20:32   ` Dave Hansen
2018-09-27 18:51   ` [tip:x86/mm] " tip-bot for Thomas Gleixner

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=20180917143545.995734490@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=bin.yang@intel.com \
    --cc=dave.hansen@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.gross@intel.com \
    --cc=peterz@infradead.org \
    --cc=x86@kernel.org \
    /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.