diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-06-13 04:36:00 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-08-24 03:23:55 -0400 |
commit | 44b6cc8130e80e673ba8b3baf8e41891fe484786 (patch) | |
tree | 08427794ef7fd6898a965addc41f672e544557b9 /arch/s390/mm | |
parent | d5dcafee5f183e9aedddb147a89cb46ab038f26b (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.c | 15 |
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: | |||
94 | struct gmap *gmap_create(struct mm_struct *mm, unsigned long limit) | 94 | struct 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); | |||
230 | void gmap_remove(struct gmap *gmap) | 236 | void 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 */ |