aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-04-15 06:45:45 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-20 03:54:18 -0400
commiteea3678d4334925bf838e6f4bc88760811a84cd6 (patch)
treeb2f259d685344030fde9d7cb7312d2e330d223a0 /arch/s390/mm
parentaa17aa57cfb95b169f25fe98caae49e477590af3 (diff)
s390/mm: flush tlb of shadows in all situations
For now, the tlb of shadow gmap is only flushed when the parent is removed, not when it is removed upfront. Therefore other shadow gmaps can reuse the tables without the tlb getting flushed. Fix this by simply flushing the tlb 1. Before the shadow tables are removed (analogouos to other unshadow functions) 2. When the gmap is freed and therefore the top level pages are freed. Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/gmap.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 6695a09a3885..b02d0d0cc641 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -173,6 +173,9 @@ static void gmap_free(struct gmap *gmap)
173{ 173{
174 struct page *page, *next; 174 struct page *page, *next;
175 175
176 /* Flush tlb of all gmaps (if not already done for shadows) */
177 if (!(gmap_is_shadow(gmap) && gmap->removed))
178 gmap_flush_tlb(gmap);
176 /* Free all segment & region tables. */ 179 /* Free all segment & region tables. */
177 list_for_each_entry_safe(page, next, &gmap->crst_list, lru) 180 list_for_each_entry_safe(page, next, &gmap->crst_list, lru)
178 __free_pages(page, 2); 181 __free_pages(page, 2);
@@ -226,13 +229,10 @@ void gmap_remove(struct gmap *gmap)
226{ 229{
227 struct gmap *sg, *next; 230 struct gmap *sg, *next;
228 231
229 /* Flush tlb. */
230 gmap_flush_tlb(gmap);
231 /* Remove all shadow gmaps linked to this gmap */ 232 /* Remove all shadow gmaps linked to this gmap */
232 if (!list_empty(&gmap->children)) { 233 if (!list_empty(&gmap->children)) {
233 spin_lock(&gmap->shadow_lock); 234 spin_lock(&gmap->shadow_lock);
234 list_for_each_entry_safe(sg, next, &gmap->children, list) { 235 list_for_each_entry_safe(sg, next, &gmap->children, list) {
235 gmap_flush_tlb(sg);
236 list_del(&sg->list); 236 list_del(&sg->list);
237 gmap_put(sg); 237 gmap_put(sg);
238 } 238 }
@@ -1360,6 +1360,7 @@ static void gmap_unshadow(struct gmap *sg)
1360 return; 1360 return;
1361 sg->removed = 1; 1361 sg->removed = 1;
1362 gmap_call_notifier(sg, 0, -1UL); 1362 gmap_call_notifier(sg, 0, -1UL);
1363 gmap_flush_tlb(sg);
1363 table = (unsigned long *)(sg->asce & _ASCE_ORIGIN); 1364 table = (unsigned long *)(sg->asce & _ASCE_ORIGIN);
1364 switch (sg->asce & _ASCE_TYPE_MASK) { 1365 switch (sg->asce & _ASCE_TYPE_MASK) {
1365 case _ASCE_TYPE_REGION1: 1366 case _ASCE_TYPE_REGION1: