2019-03-29 14:12:17 +08:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
2018-10-11 02:06:46 +08:00
|
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
|
|
Date: Mon, 17 Sep 2018 16:29:16 +0200
|
2019-03-29 14:12:17 +08:00
|
|
|
Subject: [PATCH] x86/mm/cpa: Do the range check early
|
2018-10-11 02:06:46 +08:00
|
|
|
|
|
|
|
To avoid excessive 4k wise checks in the common case do a quick check first
|
|
|
|
whether the requested new page protections conflict with a static
|
|
|
|
protection area in the large page. If there is no conflict then the
|
|
|
|
decision whether to preserve or to split the page can be made immediately.
|
|
|
|
|
|
|
|
If the requested range covers the full large page, preserve it. Otherwise
|
|
|
|
split it up. No point in doing a slow crawl in 4k steps.
|
|
|
|
|
|
|
|
Before:
|
|
|
|
|
|
|
|
1G pages checked: 2
|
|
|
|
1G pages sameprot: 0
|
|
|
|
1G pages preserved: 0
|
|
|
|
2M pages checked: 538
|
|
|
|
2M pages sameprot: 466
|
|
|
|
2M pages preserved: 47
|
|
|
|
4K pages checked: 560642
|
|
|
|
4K pages set-checked: 7668
|
|
|
|
|
|
|
|
After:
|
|
|
|
|
|
|
|
1G pages checked: 2
|
|
|
|
1G pages sameprot: 0
|
|
|
|
1G pages preserved: 0
|
|
|
|
2M pages checked: 541
|
|
|
|
2M pages sameprot: 466
|
|
|
|
2M pages preserved: 47
|
|
|
|
4K pages checked: 514
|
|
|
|
4K pages set-checked: 7668
|
|
|
|
|
|
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
|
|
Reviewed-by: Dave Hansen <dave.hansen@intel.com>
|
|
|
|
Cc: Peter Zijlstra <peterz@infradead.org>
|
|
|
|
Cc: Bin Yang <bin.yang@intel.com>
|
|
|
|
Cc: Mark Gross <mark.gross@intel.com>
|
|
|
|
Link: https://lkml.kernel.org/r/20180917143546.507259989@linutronix.de
|
|
|
|
|
|
|
|
Cc: Zhang Ning <ning.a.zhang@intel.com>
|
|
|
|
Signed-off-by: Lili Li <lili.li@intel.com>
|
|
|
|
---
|
|
|
|
arch/x86/mm/pageattr.c | 27 +++++++++++++++++++++++----
|
|
|
|
1 file changed, 23 insertions(+), 4 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
|
2020-10-27 02:14:06 +08:00
|
|
|
index 6fc4b05082a6..01da2a571a33 100644
|
2018-10-11 02:06:46 +08:00
|
|
|
--- a/arch/x86/mm/pageattr.c
|
|
|
|
+++ b/arch/x86/mm/pageattr.c
|
|
|
|
@@ -854,10 +854,28 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
- * Make sure that the requested pgprot does not violate the static
|
|
|
|
- * protections. Check the full large page whether one of the pages
|
|
|
|
- * in it results in a different pgprot than the first one of the
|
|
|
|
- * requested range. If yes, then the page needs to be split.
|
|
|
|
+ * Optimization: Check whether the requested pgprot is conflicting
|
|
|
|
+ * with a static protection requirement in the large page. If not,
|
|
|
|
+ * then checking whether the requested range is fully covering the
|
|
|
|
+ * large page can be done right here.
|
|
|
|
+ */
|
|
|
|
+ new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages,
|
|
|
|
+ CPA_DETECT);
|
|
|
|
+
|
|
|
|
+ if (pgprot_val(req_prot) == pgprot_val(new_prot)) {
|
|
|
|
+ if (address != lpaddr || cpa->numpages != numpages)
|
|
|
|
+ return 1;
|
|
|
|
+ goto setlp;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Slow path. The full large page check above established that the
|
|
|
|
+ * requested pgprot cannot be applied to the full large page due to
|
|
|
|
+ * conflicting requirements of static protection regions. It might
|
|
|
|
+ * turn out that the whole requested range is covered by the
|
|
|
|
+ * modified protection of the first 4k segment at @address. This
|
|
|
|
+ * might result in the ability to preserve the large page
|
|
|
|
+ * nevertheless.
|
|
|
|
*/
|
|
|
|
new_prot = static_protections(req_prot, address, pfn, 1, CPA_DETECT);
|
|
|
|
pfn = old_pfn;
|
|
|
|
@@ -882,6 +900,7 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
|
|
|
|
if (address != lpaddr || cpa->numpages != numpages)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
+setlp:
|
|
|
|
/* All checks passed. Update the large page mapping. */
|
|
|
|
new_pte = pfn_pte(old_pfn, new_prot);
|
|
|
|
__set_pmd_pte(kpte, address, new_pte);
|
|
|
|
--
|
2019-04-08 18:08:36 +08:00
|
|
|
https://clearlinux.org
|
2018-10-11 02:06:46 +08:00
|
|
|
|