aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2014-05-16 04:34:11 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-05-16 08:57:17 -0400
commit3a801517ad49f586f2016e1b1321e6cd28a97a04 (patch)
treeb1d3a84ccbeb491202dd2b402463a0d9e454408f /arch/s390
parentd9f89b88f5102ce235b75a5907838e3c7ed84b97 (diff)
KVM: s390: correct locking for s390_enable_skey
Use the mm semaphore to serialize multiple invocations of s390_enable_skey. The second CPU faulting on a storage key operation needs to wait for the completion of the page table update. Taking the mm semaphore writable has the positive side-effect that it prevents any host faults from taking place which does have implications on keys vs PGSTE. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/mm/pgtable.c22
1 files changed, 7 insertions, 15 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index ea4a31b95990..66ba60c9b77e 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -958,8 +958,10 @@ void page_table_reset_pgste(struct mm_struct *mm, unsigned long start,
958 unsigned long addr, next; 958 unsigned long addr, next;
959 pgd_t *pgd; 959 pgd_t *pgd;
960 960
961 down_write(&mm->mmap_sem);
962 if (init_skey && mm_use_skey(mm))
963 goto out_up;
961 addr = start; 964 addr = start;
962 down_read(&mm->mmap_sem);
963 pgd = pgd_offset(mm, addr); 965 pgd = pgd_offset(mm, addr);
964 do { 966 do {
965 next = pgd_addr_end(addr, end); 967 next = pgd_addr_end(addr, end);
@@ -967,7 +969,10 @@ void page_table_reset_pgste(struct mm_struct *mm, unsigned long start,
967 continue; 969 continue;
968 next = page_table_reset_pud(mm, pgd, addr, next, init_skey); 970 next = page_table_reset_pud(mm, pgd, addr, next, init_skey);
969 } while (pgd++, addr = next, addr != end); 971 } while (pgd++, addr = next, addr != end);
970 up_read(&mm->mmap_sem); 972 if (init_skey)
973 current->mm->context.use_skey = 1;
974out_up:
975 up_write(&mm->mmap_sem);
971} 976}
972EXPORT_SYMBOL(page_table_reset_pgste); 977EXPORT_SYMBOL(page_table_reset_pgste);
973 978
@@ -1384,19 +1389,6 @@ EXPORT_SYMBOL_GPL(s390_enable_sie);
1384 */ 1389 */
1385void s390_enable_skey(void) 1390void s390_enable_skey(void)
1386{ 1391{
1387 /*
1388 * To avoid races between multiple vcpus, ending in calling
1389 * page_table_reset twice or more,
1390 * the page_table_lock is taken for serialization.
1391 */
1392 spin_lock(&current->mm->page_table_lock);
1393 if (mm_use_skey(current->mm)) {
1394 spin_unlock(&current->mm->page_table_lock);
1395 return;
1396 }
1397
1398 current->mm->context.use_skey = 1;
1399 spin_unlock(&current->mm->page_table_lock);
1400 page_table_reset_pgste(current->mm, 0, TASK_SIZE, true); 1392 page_table_reset_pgste(current->mm, 0, TASK_SIZE, true);
1401} 1393}
1402EXPORT_SYMBOL_GPL(s390_enable_skey); 1394EXPORT_SYMBOL_GPL(s390_enable_skey);