diff options
| author | Janosch Frank <frankja@linux.ibm.com> | 2018-07-13 06:28:37 -0400 |
|---|---|---|
| committer | Janosch Frank <frankja@linux.ibm.com> | 2018-07-30 17:13:38 -0400 |
| commit | a9e00d8349c98e0973c8b0d671d69e838f7b5bcc (patch) | |
| tree | b6c9a4374f72c0f6ccea510dc8fc1f8c74d43d2d /arch | |
| parent | 7d735b9ae82d073e23ff7d2648e0aa8056049d16 (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.h | 2 | ||||
| -rw-r--r-- | arch/s390/include/asm/mmu_context.h | 1 | ||||
| -rw-r--r-- | arch/s390/mm/gmap.c | 9 | ||||
| -rw-r--r-- | arch/s390/mm/pgtable.c | 8 |
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 | } |
