linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alexandre Chartre <alexandre.chartre@oracle.com>
To: rkrcmar@redhat.com, tglx@linutronix.de, mingo@redhat.com,
	bp@alien8.de, hpa@zytor.com, dave.hansen@linux.intel.com,
	luto@kernel.org, peterz@infradead.org, x86@kernel.org,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org
Cc: pbonzini@redhat.com, konrad.wilk@oracle.com,
	jan.setjeeilers@oracle.com, liran.alon@oracle.com,
	junaids@google.com, graf@amazon.de, rppt@linux.vnet.ibm.com,
	kuzuno@gmail.com, mgross@linux.intel.com,
	alexandre.chartre@oracle.com
Subject: [RFC v4][PATCH part-1 3/7] mm/asi: Improve TLB flushing when switching to an ASI pagetable
Date: Mon,  4 May 2020 16:49:35 +0200	[thread overview]
Message-ID: <20200504144939.11318-4-alexandre.chartre@oracle.com> (raw)
In-Reply-To: <20200504144939.11318-1-alexandre.chartre@oracle.com>

When switching to an ASI pagetable, the TLB doesn't need to be flushed
if it was previously used with the same PCID. So, to avoid unnecessary
TLB flushing, we track which pagetables are used with the different
ASI PCIDs. If an ASI PCID is being used with a different ASI pagetable,
or if we have a new generation of the same ASI pagetable, then the TLB
needs to be flushed. This behavior is similar to the context tracking
done when switching mm.

Signed-off-by: Alexandre Chartre <alexandre.chartre@oracle.com>
---
 arch/x86/include/asm/asi.h | 23 +++++++++++++++++++++++
 arch/x86/mm/asi.c          | 34 ++++++++++++++++++++++++++++++++--
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/asi.h b/arch/x86/include/asm/asi.h
index 29b745ab393e..bcfb68e8e392 100644
--- a/arch/x86/include/asm/asi.h
+++ b/arch/x86/include/asm/asi.h
@@ -46,8 +46,26 @@
 
 #include <asm/asi_session.h>
 
+/*
+ * ASI_NR_DYN_ASIDS is the same as TLB_NR_DYN_ASIDS. We can't directly
+ * use TLB_NR_DYN_ASIDS because asi.h and tlbflush.h can't both include
+ * each other.
+ */
+#define ASI_TLB_NR_DYN_ASIDS	6
+
+struct asi_tlb_pgtable {
+	u64 id;
+	u64 gen;
+};
+
+struct asi_tlb_state {
+	struct asi_tlb_pgtable	tlb_pgtables[ASI_TLB_NR_DYN_ASIDS];
+};
+
 struct asi_type {
 	int			pcid_prefix;	/* PCID prefix */
+	struct asi_tlb_state	*tlb_state;	/* percpu ASI TLB state */
+	atomic64_t		last_pgtable_id; /* last id for this type */
 };
 
 /*
@@ -58,8 +76,11 @@ struct asi_type {
  * specified type.
  */
 #define DEFINE_ASI_TYPE(name, pcid_prefix)			\
+	DEFINE_PER_CPU(struct asi_tlb_state, asi_tlb_ ## name);	\
 	struct asi_type asi_type_ ## name = {			\
 		pcid_prefix,					\
+		&asi_tlb_ ## name,				\
+		ATOMIC64_INIT(1),				\
 	};							\
 	EXPORT_SYMBOL(asi_type_ ## name)
 
@@ -76,6 +97,8 @@ static inline struct asi *asi_create_ ## name(void)	\
 struct asi {
 	struct asi_type		*type;		/* ASI type */
 	pgd_t			*pagetable;	/* ASI pagetable */
+	u64			pgtable_id;	/* ASI pagetable ID */
+	atomic64_t		pgtable_gen;	/* ASI pagetable generation */
 	unsigned long		base_cr3;	/* base ASI CR3 */
 };
 
diff --git a/arch/x86/mm/asi.c b/arch/x86/mm/asi.c
index 9fbc92122ce2..cf0d122a3c72 100644
--- a/arch/x86/mm/asi.c
+++ b/arch/x86/mm/asi.c
@@ -25,6 +25,8 @@ struct asi *asi_create(struct asi_type *type)
 		return NULL;
 
 	asi->type = type;
+	asi->pgtable_id = atomic64_inc_return(&type->last_pgtable_id);
+	atomic64_set(&asi->pgtable_gen, 0);
 
 	return asi;
 }
@@ -61,6 +63,33 @@ void asi_set_pagetable(struct asi *asi, pgd_t *pagetable)
 }
 EXPORT_SYMBOL(asi_set_pagetable);
 
+/*
+ * Update ASI TLB flush information for the specified ASI CR3 value.
+ * Return an updated ASI CR3 value which specified if TLB needs to
+ * be flushed or not.
+ */
+static unsigned long asi_update_flush(struct asi *asi, unsigned long asi_cr3)
+{
+	struct asi_tlb_pgtable *tlb_pgtable;
+	struct asi_tlb_state *tlb_state;
+	s64 pgtable_gen;
+	u16 pcid;
+
+	pcid = asi_cr3 & ASI_KERNEL_PCID_MASK;
+	tlb_state = get_cpu_ptr(asi->type->tlb_state);
+	tlb_pgtable = &tlb_state->tlb_pgtables[pcid - 1];
+	pgtable_gen = atomic64_read(&asi->pgtable_gen);
+	if (tlb_pgtable->id == asi->pgtable_id &&
+	    tlb_pgtable->gen == pgtable_gen) {
+		asi_cr3 |= X86_CR3_PCID_NOFLUSH;
+	} else {
+		tlb_pgtable->id = asi->pgtable_id;
+		tlb_pgtable->gen = pgtable_gen;
+	}
+
+	return asi_cr3;
+}
+
 static void asi_switch_to_asi_cr3(struct asi *asi)
 {
 	unsigned long original_cr3, asi_cr3;
@@ -72,10 +101,11 @@ static void asi_switch_to_asi_cr3(struct asi *asi)
 	original_cr3 = __get_current_cr3_fast();
 
 	/* build the ASI cr3 value */
-	asi_cr3 = asi->base_cr3;
 	if (boot_cpu_has(X86_FEATURE_PCID)) {
 		pcid = original_cr3 & ASI_KERNEL_PCID_MASK;
-		asi_cr3 |= pcid;
+		asi_cr3 = asi_update_flush(asi, asi->base_cr3 | pcid);
+	} else {
+		asi_cr3 = asi->base_cr3;
 	}
 
 	/* get the ASI session ready for entering ASI */
-- 
2.18.2


  parent reply	other threads:[~2020-05-04 14:51 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-04 14:49 [RFC v4][PATCH part-1 0/7] ASI - Part I (ASI Infrastructure and PTI) Alexandre Chartre
2020-05-04 14:49 ` [RFC v4][PATCH part-1 1/7] mm/x86: Introduce kernel Address Space Isolation (ASI) Alexandre Chartre
2020-05-04 14:49 ` [RFC v4][PATCH part-1 2/7] mm/asi: ASI entry/exit interface Alexandre Chartre
2020-05-04 14:49 ` Alexandre Chartre [this message]
2020-05-04 14:49 ` [RFC v4][PATCH part-1 4/7] mm/asi: Interrupt ASI on interrupt/exception/NMI Alexandre Chartre
2020-05-06  7:36   ` [mm/asi] c13d1a6ed3: BUG:scheduling_while_atomic kernel test robot
2020-05-04 14:49 ` [RFC v4][PATCH part-1 5/7] mm/asi: Exit/enter ASI when task enters/exits scheduler Alexandre Chartre
2020-05-04 14:49 ` [RFC v4][PATCH part-1 6/7] mm/asi: ASI fault handler Alexandre Chartre
2020-05-04 14:49 ` [RFC v4][PATCH part-1 7/7] mm/asi: Implement PTI with ASI Alexandre Chartre
2020-05-12 17:45 ` [RFC v4][PATCH part-1 0/7] ASI - Part I (ASI Infrastructure and PTI) Dave Hansen
2020-05-12 19:25   ` Alexandre Chartre
2020-05-12 20:07   ` Andy Lutomirski

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=20200504144939.11318-4-alexandre.chartre@oracle.com \
    --to=alexandre.chartre@oracle.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=graf@amazon.de \
    --cc=hpa@zytor.com \
    --cc=jan.setjeeilers@oracle.com \
    --cc=junaids@google.com \
    --cc=konrad.wilk@oracle.com \
    --cc=kuzuno@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=liran.alon@oracle.com \
    --cc=luto@kernel.org \
    --cc=mgross@linux.intel.com \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rkrcmar@redhat.com \
    --cc=rppt@linux.vnet.ibm.com \
    --cc=tglx@linutronix.de \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).