aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2016-06-13 04:36:00 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-08-24 03:23:55 -0400
commit44b6cc8130e80e673ba8b3baf8e41891fe484786 (patch)
tree08427794ef7fd6898a965addc41f672e544557b9 /arch/s390/mm
parentd5dcafee5f183e9aedddb147a89cb46ab038f26b (diff)
s390/mm,kvm: flush gmap address space with IDTE
The __tlb_flush_mm() helper uses a global flush if the mm struct has a gmap structure attached to it. Replace the global flush with two individual flushes by means of the IDTE instruction if only a single gmap is attached the the mm. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/gmap.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 2ce6bb3bab32..3ba622702ce4 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -94,6 +94,7 @@ out:
94struct gmap *gmap_create(struct mm_struct *mm, unsigned long limit) 94struct gmap *gmap_create(struct mm_struct *mm, unsigned long limit)
95{ 95{
96 struct gmap *gmap; 96 struct gmap *gmap;
97 unsigned long gmap_asce;
97 98
98 gmap = gmap_alloc(limit); 99 gmap = gmap_alloc(limit);
99 if (!gmap) 100 if (!gmap)
@@ -101,6 +102,11 @@ struct gmap *gmap_create(struct mm_struct *mm, unsigned long limit)
101 gmap->mm = mm; 102 gmap->mm = mm;
102 spin_lock(&mm->context.gmap_lock); 103 spin_lock(&mm->context.gmap_lock);
103 list_add_rcu(&gmap->list, &mm->context.gmap_list); 104 list_add_rcu(&gmap->list, &mm->context.gmap_list);
105 if (list_is_singular(&mm->context.gmap_list))
106 gmap_asce = gmap->asce;
107 else
108 gmap_asce = -1UL;
109 WRITE_ONCE(mm->context.gmap_asce, gmap_asce);
104 spin_unlock(&mm->context.gmap_lock); 110 spin_unlock(&mm->context.gmap_lock);
105 return gmap; 111 return gmap;
106} 112}
@@ -230,6 +236,7 @@ EXPORT_SYMBOL_GPL(gmap_put);
230void gmap_remove(struct gmap *gmap) 236void gmap_remove(struct gmap *gmap)
231{ 237{
232 struct gmap *sg, *next; 238 struct gmap *sg, *next;
239 unsigned long gmap_asce;
233 240
234 /* Remove all shadow gmaps linked to this gmap */ 241 /* Remove all shadow gmaps linked to this gmap */
235 if (!list_empty(&gmap->children)) { 242 if (!list_empty(&gmap->children)) {
@@ -243,6 +250,14 @@ void gmap_remove(struct gmap *gmap)
243 /* Remove gmap from the pre-mm list */ 250 /* Remove gmap from the pre-mm list */
244 spin_lock(&gmap->mm->context.gmap_lock); 251 spin_lock(&gmap->mm->context.gmap_lock);
245 list_del_rcu(&gmap->list); 252 list_del_rcu(&gmap->list);
253 if (list_empty(&gmap->mm->context.gmap_list))
254 gmap_asce = 0;
255 else if (list_is_singular(&gmap->mm->context.gmap_list))
256 gmap_asce = list_first_entry(&gmap->mm->context.gmap_list,
257 struct gmap, list)->asce;
258 else
259 gmap_asce = -1UL;
260 WRITE_ONCE(gmap->mm->context.gmap_asce, gmap_asce);
246 spin_unlock(&gmap->mm->context.gmap_lock); 261 spin_unlock(&gmap->mm->context.gmap_lock);
247 synchronize_rcu(); 262 synchronize_rcu();
248 /* Put reference */ 263 /* Put reference */