Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/mm: disable KSM for storage key enabled pages

When storage keys are enabled unmerge already merged pages and prevent
new pages from being merged.

Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Dominik Dingel and committed by
Martin Schwidefsky
3ac8e380 2faee8ff

+28 -7
+1 -1
arch/s390/include/asm/pgtable.h
··· 1751 1751 extern int vmem_add_mapping(unsigned long start, unsigned long size); 1752 1752 extern int vmem_remove_mapping(unsigned long start, unsigned long size); 1753 1753 extern int s390_enable_sie(void); 1754 - extern void s390_enable_skey(void); 1754 + extern int s390_enable_skey(void); 1755 1755 extern void s390_reset_cmma(struct mm_struct *mm); 1756 1756 1757 1757 /*
+12 -5
arch/s390/kvm/priv.c
··· 156 156 return 0; 157 157 } 158 158 159 - static void __skey_check_enable(struct kvm_vcpu *vcpu) 159 + static int __skey_check_enable(struct kvm_vcpu *vcpu) 160 160 { 161 + int rc = 0; 161 162 if (!(vcpu->arch.sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE))) 162 - return; 163 + return rc; 163 164 164 - s390_enable_skey(); 165 + rc = s390_enable_skey(); 165 166 trace_kvm_s390_skey_related_inst(vcpu); 166 167 vcpu->arch.sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE); 168 + return rc; 167 169 } 168 170 169 171 170 172 static int handle_skey(struct kvm_vcpu *vcpu) 171 173 { 172 - __skey_check_enable(vcpu); 174 + int rc = __skey_check_enable(vcpu); 173 175 176 + if (rc) 177 + return rc; 174 178 vcpu->stat.instruction_storage_key++; 175 179 176 180 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) ··· 687 683 } 688 684 689 685 if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) { 690 - __skey_check_enable(vcpu); 686 + int rc = __skey_check_enable(vcpu); 687 + 688 + if (rc) 689 + return rc; 691 690 if (set_guest_storage_key(current->mm, useraddr, 692 691 vcpu->run->s.regs.gprs[reg1] & PFMF_KEY, 693 692 vcpu->run->s.regs.gprs[reg1] & PFMF_NQ))
+15 -1
arch/s390/mm/pgtable.c
··· 18 18 #include <linux/rcupdate.h> 19 19 #include <linux/slab.h> 20 20 #include <linux/swapops.h> 21 + #include <linux/ksm.h> 22 + #include <linux/mman.h> 21 23 22 24 #include <asm/pgtable.h> 23 25 #include <asm/pgalloc.h> ··· 1277 1275 return 0; 1278 1276 } 1279 1277 1280 - void s390_enable_skey(void) 1278 + int s390_enable_skey(void) 1281 1279 { 1282 1280 struct mm_walk walk = { .pte_entry = __s390_enable_skey }; 1283 1281 struct mm_struct *mm = current->mm; 1282 + struct vm_area_struct *vma; 1283 + int rc = 0; 1284 1284 1285 1285 down_write(&mm->mmap_sem); 1286 1286 if (mm_use_skey(mm)) 1287 1287 goto out_up; 1288 1288 1289 1289 mm->context.use_skey = 1; 1290 + for (vma = mm->mmap; vma; vma = vma->vm_next) { 1291 + if (ksm_madvise(vma, vma->vm_start, vma->vm_end, 1292 + MADV_UNMERGEABLE, &vma->vm_flags)) { 1293 + mm->context.use_skey = 0; 1294 + rc = -ENOMEM; 1295 + goto out_up; 1296 + } 1297 + } 1298 + mm->def_flags &= ~VM_MERGEABLE; 1290 1299 1291 1300 walk.mm = mm; 1292 1301 walk_page_range(0, TASK_SIZE, &walk); 1293 1302 1294 1303 out_up: 1295 1304 up_write(&mm->mmap_sem); 1305 + return rc; 1296 1306 } 1297 1307 EXPORT_SYMBOL_GPL(s390_enable_skey); 1298 1308