aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJanosch Frank <frankja@linux.ibm.com>2018-07-13 06:28:37 -0400
committerJanosch Frank <frankja@linux.ibm.com>2018-07-30 17:13:38 -0400
commita9e00d8349c98e0973c8b0d671d69e838f7b5bcc (patch)
treeb6c9a4374f72c0f6ccea510dc8fc1f8c74d43d2d /arch
parent7d735b9ae82d073e23ff7d2648e0aa8056049d16 (diff)
s390/mm: Add huge page gmap linking support
Let's allow huge pmd linking when enabled through the KVM_CAP_S390_HPAGE_1M capability. Also we can now restrict gmap invalidation and notification to the cases where the capability has been activated and save some cycles when that's not the case. Signed-off-by: Janosch Frank <frankja@linux.ibm.com> Reviewed-by: David Hildenbrand <david@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/mmu.h2
-rw-r--r--arch/s390/include/asm/mmu_context.h1
-rw-r--r--arch/s390/mm/gmap.c9
-rw-r--r--arch/s390/mm/pgtable.c8
4 files changed, 13 insertions, 7 deletions
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
index f5ff9dbad8ac..f31a15044c24 100644
--- a/arch/s390/include/asm/mmu.h
+++ b/arch/s390/include/asm/mmu.h
@@ -24,6 +24,8 @@ typedef struct {
24 unsigned int uses_skeys:1; 24 unsigned int uses_skeys:1;
25 /* The mmu context uses CMM. */ 25 /* The mmu context uses CMM. */
26 unsigned int uses_cmm:1; 26 unsigned int uses_cmm:1;
27 /* The gmaps associated with this context are allowed to use huge pages. */
28 unsigned int allow_gmap_hpage_1m:1;
27} mm_context_t; 29} mm_context_t;
28 30
29#define INIT_MM_CONTEXT(name) \ 31#define INIT_MM_CONTEXT(name) \
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index d16bc79c30bb..0717ee76885d 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -32,6 +32,7 @@ static inline int init_new_context(struct task_struct *tsk,
32 mm->context.has_pgste = 0; 32 mm->context.has_pgste = 0;
33 mm->context.uses_skeys = 0; 33 mm->context.uses_skeys = 0;
34 mm->context.uses_cmm = 0; 34 mm->context.uses_cmm = 0;
35 mm->context.allow_gmap_hpage_1m = 0;
35#endif 36#endif
36 switch (mm->context.asce_limit) { 37 switch (mm->context.asce_limit) {
37 case _REGION2_SIZE: 38 case _REGION2_SIZE:
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 736ed32a83c5..bb44990c8212 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -2,8 +2,10 @@
2/* 2/*
3 * KVM guest address space mapping code 3 * KVM guest address space mapping code
4 * 4 *
5 * Copyright IBM Corp. 2007, 2016 5 * Copyright IBM Corp. 2007, 2016, 2018
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 * David Hildenbrand <david@redhat.com>
8 * Janosch Frank <frankja@linux.vnet.ibm.com>
7 */ 9 */
8 10
9#include <linux/kernel.h> 11#include <linux/kernel.h>
@@ -588,8 +590,8 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
588 return -EFAULT; 590 return -EFAULT;
589 pmd = pmd_offset(pud, vmaddr); 591 pmd = pmd_offset(pud, vmaddr);
590 VM_BUG_ON(pmd_none(*pmd)); 592 VM_BUG_ON(pmd_none(*pmd));
591 /* large pmds cannot yet be handled */ 593 /* Are we allowed to use huge pages? */
592 if (pmd_large(*pmd)) 594 if (pmd_large(*pmd) && !gmap->mm->context.allow_gmap_hpage_1m)
593 return -EFAULT; 595 return -EFAULT;
594 /* Link gmap segment table entry location to page table. */ 596 /* Link gmap segment table entry location to page table. */
595 rc = radix_tree_preload(GFP_KERNEL); 597 rc = radix_tree_preload(GFP_KERNEL);
@@ -1632,6 +1634,7 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce,
1632 unsigned long limit; 1634 unsigned long limit;
1633 int rc; 1635 int rc;
1634 1636
1637 BUG_ON(parent->mm->context.allow_gmap_hpage_1m);
1635 BUG_ON(gmap_is_shadow(parent)); 1638 BUG_ON(gmap_is_shadow(parent));
1636 spin_lock(&parent->shadow_lock); 1639 spin_lock(&parent->shadow_lock);
1637 sg = gmap_find_shadow(parent, asce, edat_level); 1640 sg = gmap_find_shadow(parent, asce, edat_level);
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 37d68706f5aa..f2cc7da473e4 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -347,7 +347,7 @@ static inline void pmdp_idte_local(struct mm_struct *mm,
347 mm->context.asce, IDTE_LOCAL); 347 mm->context.asce, IDTE_LOCAL);
348 else 348 else
349 __pmdp_idte(addr, pmdp, 0, 0, IDTE_LOCAL); 349 __pmdp_idte(addr, pmdp, 0, 0, IDTE_LOCAL);
350 if (mm_has_pgste(mm)) 350 if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
351 gmap_pmdp_idte_local(mm, addr); 351 gmap_pmdp_idte_local(mm, addr);
352} 352}
353 353
@@ -357,15 +357,15 @@ static inline void pmdp_idte_global(struct mm_struct *mm,
357 if (MACHINE_HAS_TLB_GUEST) { 357 if (MACHINE_HAS_TLB_GUEST) {
358 __pmdp_idte(addr, pmdp, IDTE_NODAT | IDTE_GUEST_ASCE, 358 __pmdp_idte(addr, pmdp, IDTE_NODAT | IDTE_GUEST_ASCE,
359 mm->context.asce, IDTE_GLOBAL); 359 mm->context.asce, IDTE_GLOBAL);
360 if (mm_has_pgste(mm)) 360 if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
361 gmap_pmdp_idte_global(mm, addr); 361 gmap_pmdp_idte_global(mm, addr);
362 } else if (MACHINE_HAS_IDTE) { 362 } else if (MACHINE_HAS_IDTE) {
363 __pmdp_idte(addr, pmdp, 0, 0, IDTE_GLOBAL); 363 __pmdp_idte(addr, pmdp, 0, 0, IDTE_GLOBAL);
364 if (mm_has_pgste(mm)) 364 if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
365 gmap_pmdp_idte_global(mm, addr); 365 gmap_pmdp_idte_global(mm, addr);
366 } else { 366 } else {
367 __pmdp_csp(pmdp); 367 __pmdp_csp(pmdp);
368 if (mm_has_pgste(mm)) 368 if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
369 gmap_pmdp_csp(mm, addr); 369 gmap_pmdp_csp(mm, addr);
370 } 370 }
371} 371}