diff options
author | Carsten Otte <cotte@de.ibm.com> | 2011-10-30 15:17:02 +0100 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2011-10-30 15:16:45 +0100 |
commit | 499069e1a421e2a85e76846c3237f00f1a5cb435 (patch) | |
tree | 01cf74636909b06b5a986f97a90bf0af5040212d /arch/s390/mm/pgtable.c | |
parent | cc772456ac9b460693492b3a3d89e8c81eda5874 (diff) | |
download | kernel_goldelico_gta04-499069e1a421e2a85e76846c3237f00f1a5cb435.zip kernel_goldelico_gta04-499069e1a421e2a85e76846c3237f00f1a5cb435.tar.gz kernel_goldelico_gta04-499069e1a421e2a85e76846c3237f00f1a5cb435.tar.bz2 |
[S390] take mmap_sem when walking guest page table
gmap_fault needs to walk the guest page table. However, parts of
that may change if some other thread does munmap. In that case
gmap_unmap_notifier will also unmap the corresponding parts from
the guest page table. We need to take mmap_sem in order to serialize
these operations.
do_exception now calls __gmap_fault with mmap_sem held which does
not get exported to modules. The exported function, which is called
from KVM, now takes mmap_sem.
Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/mm/pgtable.c')
-rw-r--r-- | arch/s390/mm/pgtable.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 96e85ac..441d344 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -393,7 +393,10 @@ out_unmap: } EXPORT_SYMBOL_GPL(gmap_map_segment); -unsigned long gmap_fault(unsigned long address, struct gmap *gmap) +/* + * this function is assumed to be called with mmap_sem held + */ +unsigned long __gmap_fault(unsigned long address, struct gmap *gmap) { unsigned long *table, vmaddr, segment; struct mm_struct *mm; @@ -461,7 +464,17 @@ unsigned long gmap_fault(unsigned long address, struct gmap *gmap) return vmaddr | (address & ~PMD_MASK); } return -EFAULT; +} + +unsigned long gmap_fault(unsigned long address, struct gmap *gmap) +{ + unsigned long rc; + + down_read(&gmap->mm->mmap_sem); + rc = __gmap_fault(address, gmap); + up_read(&gmap->mm->mmap_sem); + return rc; } EXPORT_SYMBOL_GPL(gmap_fault); |