linux-s390.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christian Borntraeger <borntraeger@de.ibm.com>
To: "Paolo Bonzini" <pbonzini@redhat.com>,
	"Radim Krčmář" <rkrcmar@redhat.com>
Cc: KVM <kvm@vger.kernel.org>,
	Cornelia Huck <cornelia.huck@de.ibm.com>,
	linux-s390 <linux-s390@vger.kernel.org>,
	Christian Borntraeger <borntraeger@de.ibm.com>,
	David Hildenbrand <dahi@linux.vnet.ibm.com>,
	Martin Schwidefsky <schwidefsky@de.ibm.com>
Subject: [GIT PULL 02/51] s390/mm: use RCU for gmap notifier list and the per-mm gmap list
Date: Tue, 21 Jun 2016 15:12:40 +0200	[thread overview]
Message-ID: <1466514809-146638-3-git-send-email-borntraeger@de.ibm.com> (raw)
In-Reply-To: <1466514809-146638-1-git-send-email-borntraeger@de.ibm.com>

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

The gmap notifier list and the gmap list in the mm_struct change rarely.
Use RCU to optimize the reader of these lists.

Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 arch/s390/include/asm/gmap.h        |  1 +
 arch/s390/include/asm/mmu.h         | 11 +++++++----
 arch/s390/include/asm/mmu_context.h |  3 ++-
 arch/s390/mm/gmap.c                 | 39 ++++++++++++++++++++++---------------
 arch/s390/mm/pgalloc.c              | 16 +++++++--------
 5 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h
index bc0eadf..2cf49624 100644
--- a/arch/s390/include/asm/gmap.h
+++ b/arch/s390/include/asm/gmap.h
@@ -39,6 +39,7 @@ struct gmap {
  */
 struct gmap_notifier {
 	struct list_head list;
+	struct rcu_head rcu;
 	void (*notifier_call)(struct gmap *gmap, unsigned long start,
 			      unsigned long end);
 };
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
index 081b2ad..b941528 100644
--- a/arch/s390/include/asm/mmu.h
+++ b/arch/s390/include/asm/mmu.h
@@ -8,8 +8,9 @@ typedef struct {
 	cpumask_t cpu_attach_mask;
 	atomic_t attach_count;
 	unsigned int flush_mm;
-	spinlock_t list_lock;
+	spinlock_t pgtable_lock;
 	struct list_head pgtable_list;
+	spinlock_t gmap_lock;
 	struct list_head gmap_list;
 	unsigned long asce;
 	unsigned long asce_limit;
@@ -22,9 +23,11 @@ typedef struct {
 	unsigned int use_skey:1;
 } mm_context_t;
 
-#define INIT_MM_CONTEXT(name)						      \
-	.context.list_lock    = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \
-	.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),    \
+#define INIT_MM_CONTEXT(name)						   \
+	.context.pgtable_lock =						   \
+			__SPIN_LOCK_UNLOCKED(name.context.pgtable_lock),   \
+	.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \
+	.context.gmap_lock = __SPIN_LOCK_UNLOCKED(name.context.gmap_lock), \
 	.context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),
 
 static inline int tprot(unsigned long addr)
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index c837b79..3ce3854 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -15,8 +15,9 @@
 static inline int init_new_context(struct task_struct *tsk,
 				   struct mm_struct *mm)
 {
-	spin_lock_init(&mm->context.list_lock);
+	spin_lock_init(&mm->context.pgtable_lock);
 	INIT_LIST_HEAD(&mm->context.pgtable_list);
+	spin_lock_init(&mm->context.gmap_lock);
 	INIT_LIST_HEAD(&mm->context.gmap_list);
 	cpumask_clear(&mm->context.cpu_attach_mask);
 	atomic_set(&mm->context.attach_count, 0);
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index b5820bf..8b56423 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -70,9 +70,9 @@ struct gmap *gmap_alloc(struct mm_struct *mm, unsigned long limit)
 	gmap->asce = atype | _ASCE_TABLE_LENGTH |
 		_ASCE_USER_BITS | __pa(table);
 	gmap->asce_end = limit;
-	down_write(&mm->mmap_sem);
-	list_add(&gmap->list, &mm->context.gmap_list);
-	up_write(&mm->mmap_sem);
+	spin_lock(&mm->context.gmap_lock);
+	list_add_rcu(&gmap->list, &mm->context.gmap_list);
+	spin_unlock(&mm->context.gmap_lock);
 	return gmap;
 
 out_free:
@@ -128,14 +128,16 @@ void gmap_free(struct gmap *gmap)
 	else
 		__tlb_flush_global();
 
+	spin_lock(&gmap->mm->context.gmap_lock);
+	list_del_rcu(&gmap->list);
+	spin_unlock(&gmap->mm->context.gmap_lock);
+	synchronize_rcu();
+
 	/* Free all segment & region tables. */
 	list_for_each_entry_safe(page, next, &gmap->crst_list, lru)
 		__free_pages(page, 2);
 	gmap_radix_tree_free(&gmap->guest_to_host);
 	gmap_radix_tree_free(&gmap->host_to_guest);
-	down_write(&gmap->mm->mmap_sem);
-	list_del(&gmap->list);
-	up_write(&gmap->mm->mmap_sem);
 	kfree(gmap);
 }
 EXPORT_SYMBOL_GPL(gmap_free);
@@ -369,11 +371,13 @@ void gmap_unlink(struct mm_struct *mm, unsigned long *table,
 	struct gmap *gmap;
 	int flush;
 
-	list_for_each_entry(gmap, &mm->context.gmap_list, list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) {
 		flush = __gmap_unlink_by_vmaddr(gmap, vmaddr);
 		if (flush)
 			gmap_flush_tlb(gmap);
 	}
+	rcu_read_unlock();
 }
 
 /**
@@ -555,7 +559,7 @@ static DEFINE_SPINLOCK(gmap_notifier_lock);
 void gmap_register_ipte_notifier(struct gmap_notifier *nb)
 {
 	spin_lock(&gmap_notifier_lock);
-	list_add(&nb->list, &gmap_notifier_list);
+	list_add_rcu(&nb->list, &gmap_notifier_list);
 	spin_unlock(&gmap_notifier_lock);
 }
 EXPORT_SYMBOL_GPL(gmap_register_ipte_notifier);
@@ -567,8 +571,9 @@ EXPORT_SYMBOL_GPL(gmap_register_ipte_notifier);
 void gmap_unregister_ipte_notifier(struct gmap_notifier *nb)
 {
 	spin_lock(&gmap_notifier_lock);
-	list_del_init(&nb->list);
+	list_del_rcu(&nb->list);
 	spin_unlock(&gmap_notifier_lock);
+	synchronize_rcu();
 }
 EXPORT_SYMBOL_GPL(gmap_unregister_ipte_notifier);
 
@@ -662,16 +667,18 @@ void ptep_notify(struct mm_struct *mm, unsigned long vmaddr, pte_t *pte)
 
 	offset = ((unsigned long) pte) & (255 * sizeof(pte_t));
 	offset = offset * (4096 / sizeof(pte_t));
-	spin_lock(&gmap_notifier_lock);
-	list_for_each_entry(gmap, &mm->context.gmap_list, list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) {
+		spin_lock(&gmap->guest_table_lock);
 		table = radix_tree_lookup(&gmap->host_to_guest,
 					  vmaddr >> PMD_SHIFT);
-		if (!table)
-			continue;
-		gaddr = __gmap_segment_gaddr(table) + offset;
-		gmap_call_notifier(gmap, gaddr, gaddr + PAGE_SIZE - 1);
+		if (table)
+			gaddr = __gmap_segment_gaddr(table) + offset;
+		spin_unlock(&gmap->guest_table_lock);
+		if (table)
+			gmap_call_notifier(gmap, gaddr, gaddr + PAGE_SIZE - 1);
 	}
-	spin_unlock(&gmap_notifier_lock);
+	rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(ptep_notify);
 
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
index e8b5962..7be1f94 100644
--- a/arch/s390/mm/pgalloc.c
+++ b/arch/s390/mm/pgalloc.c
@@ -149,7 +149,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
 	/* Try to get a fragment of a 4K page as a 2K page table */
 	if (!mm_alloc_pgste(mm)) {
 		table = NULL;
-		spin_lock_bh(&mm->context.list_lock);
+		spin_lock_bh(&mm->context.pgtable_lock);
 		if (!list_empty(&mm->context.pgtable_list)) {
 			page = list_first_entry(&mm->context.pgtable_list,
 						struct page, lru);
@@ -164,7 +164,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
 				list_del(&page->lru);
 			}
 		}
-		spin_unlock_bh(&mm->context.list_lock);
+		spin_unlock_bh(&mm->context.pgtable_lock);
 		if (table)
 			return table;
 	}
@@ -187,9 +187,9 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
 		/* Return the first 2K fragment of the page */
 		atomic_set(&page->_mapcount, 1);
 		clear_table(table, _PAGE_INVALID, PAGE_SIZE);
-		spin_lock_bh(&mm->context.list_lock);
+		spin_lock_bh(&mm->context.pgtable_lock);
 		list_add(&page->lru, &mm->context.pgtable_list);
-		spin_unlock_bh(&mm->context.list_lock);
+		spin_unlock_bh(&mm->context.pgtable_lock);
 	}
 	return table;
 }
@@ -203,13 +203,13 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
 	if (!mm_alloc_pgste(mm)) {
 		/* Free 2K page table fragment of a 4K page */
 		bit = (__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
-		spin_lock_bh(&mm->context.list_lock);
+		spin_lock_bh(&mm->context.pgtable_lock);
 		mask = atomic_xor_bits(&page->_mapcount, 1U << bit);
 		if (mask & 3)
 			list_add(&page->lru, &mm->context.pgtable_list);
 		else
 			list_del(&page->lru);
-		spin_unlock_bh(&mm->context.list_lock);
+		spin_unlock_bh(&mm->context.pgtable_lock);
 		if (mask != 0)
 			return;
 	}
@@ -235,13 +235,13 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
 		return;
 	}
 	bit = (__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t));
-	spin_lock_bh(&mm->context.list_lock);
+	spin_lock_bh(&mm->context.pgtable_lock);
 	mask = atomic_xor_bits(&page->_mapcount, 0x11U << bit);
 	if (mask & 3)
 		list_add_tail(&page->lru, &mm->context.pgtable_list);
 	else
 		list_del(&page->lru);
-	spin_unlock_bh(&mm->context.list_lock);
+	spin_unlock_bh(&mm->context.pgtable_lock);
 	table = (unsigned long *) (__pa(table) | (1U << bit));
 	tlb_remove_table(tlb, table);
 }
-- 
2.5.5

  parent reply	other threads:[~2016-06-21 13:12 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-21 13:12 [GIT PULL 00/51] KVM: s390: vSIE (nested virtualization) feature for 4.8 (kvm/next) Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 01/51] s390/kvm: page table invalidation notifier Christian Borntraeger
2016-06-21 13:12 ` Christian Borntraeger [this message]
2016-06-21 13:12 ` [GIT PULL 03/51] s390/mm: extended gmap pte notifier Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 04/51] s390/mm: add reference counter to gmap structure Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 05/51] s390/mm: add shadow gmap support Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 06/51] s390/mm: add kvm shadow fault function Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 07/51] s390/mm: flush tlb of shadows in all situations Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 08/51] s390/mm: shadow pages with real guest requested protection Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 09/51] s390/mm: avoid races on region/segment/page table shadowing Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 10/51] s390/mm: fix races on gmap_shadow creation Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 11/51] s390/mm: take the mmap_sem in kvm_s390_shadow_fault() Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 12/51] s390/mm: protection exceptions are corrrectly shadowed Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 13/51] s390/mm: take ipte_lock during shadow faults Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 14/51] s390/mm: push ste protection down to shadow pte Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 15/51] s390/mm: prepare for EDAT1/EDAT2 support in gmap shadow Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 16/51] s390/mm: support EDAT1 for gmap shadows Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 17/51] s390/mm: support EDAT2 " Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 18/51] s390/mm: push rte protection down to shadow pte Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 19/51] s390/mm: support real-space for gmap shadows Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 20/51] s390/mm: limit number of real-space " Christian Borntraeger
2016-06-21 13:12 ` [GIT PULL 21/51] s390/mm: remember the int code for the last gmap fault Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 22/51] s390/mm: allow to check if a gmap shadow is valid Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 23/51] s390/mm: don't fault everything in read-write in gmap_pte_op_fixup() Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 24/51] KVM: s390: fast path for shadow gmaps in gmap notifier Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 25/51] KVM: s390: backup the currently enabled gmap when scheduled out Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 26/51] s390: introduce page_to_virt() and pfn_to_virt() Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 27/51] mm/page_ref: introduce page_ref_inc_return Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 28/51] KVM: s390: vsie: initial support for nested virtualization Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 29/51] KVM: s390: vsie: optimize gmap prefix mapping Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 30/51] KVM: s390: vsie: support setting the ibc Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 31/51] KVM: s390: vsie: support edat1 / edat2 Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 32/51] KVM: s390: vsie: support host-protection-interruption Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 33/51] KVM: s390: vsie: support STFLE interpretation Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 34/51] KVM: s390: vsie: support aes dea wrapping keys Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 35/51] KVM: s390: vsie: support transactional execution Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 36/51] KVM: s390: vsie: support vectory facility (SIMD) Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 37/51] KVM: s390: vsie: support run-time-instrumentation Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 38/51] KVM: s390: vsie: support 64-bit-SCAO Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 39/51] KVM: s390: vsie: support shared IPTE-interlock facility Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 40/51] KVM: s390: vsie: support guest-PER-enhancement Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 41/51] KVM: s390: vsie: support guest-storage-limit-suppression Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 42/51] KVM: s390: vsie: support intervention-bypass Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 43/51] KVM: s390: vsie: support conditional-external-interception Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 44/51] KVM: s390: vsie: support IBS interpretation Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 45/51] KVM: s390: vsie: try to refault after a reported fault to g2 Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 46/51] KVM: s390: vsie: speed up VCPU irq delivery when handling vsie Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 47/51] KVM: s390: don't use CPUSTAT_WAIT to detect if a VCPU is idle Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 48/51] KVM: s390: vsie: speed up VCPU external calls Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 49/51] KVM: s390: vsie: correctly set and handle guest TOD Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 50/51] KVM: s390: vsie: add indication for future features Christian Borntraeger
2016-06-21 13:13 ` [GIT PULL 51/51] KVM: s390: vsie: add module parameter "nested" Christian Borntraeger
2016-06-21 13:22 ` [GIT PULL 00/51] KVM: s390: vSIE (nested virtualization) feature for 4.8 (kvm/next) Paolo Bonzini

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=1466514809-146638-3-git-send-email-borntraeger@de.ibm.com \
    --to=borntraeger@de.ibm.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=dahi@linux.vnet.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.com \
    --cc=schwidefsky@de.ibm.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 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).