Commit 3a801517 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Christian Borntraeger

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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent d9f89b88
...@@ -958,8 +958,10 @@ void page_table_reset_pgste(struct mm_struct *mm, unsigned long start, ...@@ -958,8 +958,10 @@ void page_table_reset_pgste(struct mm_struct *mm, unsigned long start,
unsigned long addr, next; unsigned long addr, next;
pgd_t *pgd; pgd_t *pgd;
down_write(&mm->mmap_sem);
if (init_skey && mm_use_skey(mm))
goto out_up;
addr = start; addr = start;
down_read(&mm->mmap_sem);
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
do { do {
next = pgd_addr_end(addr, end); next = pgd_addr_end(addr, end);
...@@ -967,7 +969,10 @@ void page_table_reset_pgste(struct mm_struct *mm, unsigned long start, ...@@ -967,7 +969,10 @@ void page_table_reset_pgste(struct mm_struct *mm, unsigned long start,
continue; continue;
next = page_table_reset_pud(mm, pgd, addr, next, init_skey); next = page_table_reset_pud(mm, pgd, addr, next, init_skey);
} while (pgd++, addr = next, addr != end); } while (pgd++, addr = next, addr != end);
up_read(&mm->mmap_sem); if (init_skey)
current->mm->context.use_skey = 1;
out_up:
up_write(&mm->mmap_sem);
} }
EXPORT_SYMBOL(page_table_reset_pgste); EXPORT_SYMBOL(page_table_reset_pgste);
...@@ -1384,19 +1389,6 @@ EXPORT_SYMBOL_GPL(s390_enable_sie); ...@@ -1384,19 +1389,6 @@ EXPORT_SYMBOL_GPL(s390_enable_sie);
*/ */
void s390_enable_skey(void) void s390_enable_skey(void)
{ {
/*
* To avoid races between multiple vcpus, ending in calling
* page_table_reset twice or more,
* the page_table_lock is taken for serialization.
*/
spin_lock(&current->mm->page_table_lock);
if (mm_use_skey(current->mm)) {
spin_unlock(&current->mm->page_table_lock);
return;
}
current->mm->context.use_skey = 1;
spin_unlock(&current->mm->page_table_lock);
page_table_reset_pgste(current->mm, 0, TASK_SIZE, true); page_table_reset_pgste(current->mm, 0, TASK_SIZE, true);
} }
EXPORT_SYMBOL_GPL(s390_enable_skey); EXPORT_SYMBOL_GPL(s390_enable_skey);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment