Commit a9e00d83 authored by Janosch Frank's avatar Janosch Frank

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: default avatarJanosch Frank <frankja@linux.ibm.com>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
parent 7d735b9a
...@@ -24,6 +24,8 @@ typedef struct { ...@@ -24,6 +24,8 @@ typedef struct {
unsigned int uses_skeys:1; unsigned int uses_skeys:1;
/* The mmu context uses CMM. */ /* The mmu context uses CMM. */
unsigned int uses_cmm:1; unsigned int uses_cmm:1;
/* The gmaps associated with this context are allowed to use huge pages. */
unsigned int allow_gmap_hpage_1m:1;
} mm_context_t; } mm_context_t;
#define INIT_MM_CONTEXT(name) \ #define INIT_MM_CONTEXT(name) \
......
...@@ -32,6 +32,7 @@ static inline int init_new_context(struct task_struct *tsk, ...@@ -32,6 +32,7 @@ static inline int init_new_context(struct task_struct *tsk,
mm->context.has_pgste = 0; mm->context.has_pgste = 0;
mm->context.uses_skeys = 0; mm->context.uses_skeys = 0;
mm->context.uses_cmm = 0; mm->context.uses_cmm = 0;
mm->context.allow_gmap_hpage_1m = 0;
#endif #endif
switch (mm->context.asce_limit) { switch (mm->context.asce_limit) {
case _REGION2_SIZE: case _REGION2_SIZE:
......
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
/* /*
* KVM guest address space mapping code * KVM guest address space mapping code
* *
* Copyright IBM Corp. 2007, 2016 * Copyright IBM Corp. 2007, 2016, 2018
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
* David Hildenbrand <david@redhat.com>
* Janosch Frank <frankja@linux.vnet.ibm.com>
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -588,8 +590,8 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr) ...@@ -588,8 +590,8 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
return -EFAULT; return -EFAULT;
pmd = pmd_offset(pud, vmaddr); pmd = pmd_offset(pud, vmaddr);
VM_BUG_ON(pmd_none(*pmd)); VM_BUG_ON(pmd_none(*pmd));
/* large pmds cannot yet be handled */ /* Are we allowed to use huge pages? */
if (pmd_large(*pmd)) if (pmd_large(*pmd) && !gmap->mm->context.allow_gmap_hpage_1m)
return -EFAULT; return -EFAULT;
/* Link gmap segment table entry location to page table. */ /* Link gmap segment table entry location to page table. */
rc = radix_tree_preload(GFP_KERNEL); rc = radix_tree_preload(GFP_KERNEL);
...@@ -1632,6 +1634,7 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, ...@@ -1632,6 +1634,7 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce,
unsigned long limit; unsigned long limit;
int rc; int rc;
BUG_ON(parent->mm->context.allow_gmap_hpage_1m);
BUG_ON(gmap_is_shadow(parent)); BUG_ON(gmap_is_shadow(parent));
spin_lock(&parent->shadow_lock); spin_lock(&parent->shadow_lock);
sg = gmap_find_shadow(parent, asce, edat_level); sg = gmap_find_shadow(parent, asce, edat_level);
......
...@@ -347,7 +347,7 @@ static inline void pmdp_idte_local(struct mm_struct *mm, ...@@ -347,7 +347,7 @@ static inline void pmdp_idte_local(struct mm_struct *mm,
mm->context.asce, IDTE_LOCAL); mm->context.asce, IDTE_LOCAL);
else else
__pmdp_idte(addr, pmdp, 0, 0, IDTE_LOCAL); __pmdp_idte(addr, pmdp, 0, 0, IDTE_LOCAL);
if (mm_has_pgste(mm)) if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
gmap_pmdp_idte_local(mm, addr); gmap_pmdp_idte_local(mm, addr);
} }
...@@ -357,15 +357,15 @@ static inline void pmdp_idte_global(struct mm_struct *mm, ...@@ -357,15 +357,15 @@ static inline void pmdp_idte_global(struct mm_struct *mm,
if (MACHINE_HAS_TLB_GUEST) { if (MACHINE_HAS_TLB_GUEST) {
__pmdp_idte(addr, pmdp, IDTE_NODAT | IDTE_GUEST_ASCE, __pmdp_idte(addr, pmdp, IDTE_NODAT | IDTE_GUEST_ASCE,
mm->context.asce, IDTE_GLOBAL); mm->context.asce, IDTE_GLOBAL);
if (mm_has_pgste(mm)) if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
gmap_pmdp_idte_global(mm, addr); gmap_pmdp_idte_global(mm, addr);
} else if (MACHINE_HAS_IDTE) { } else if (MACHINE_HAS_IDTE) {
__pmdp_idte(addr, pmdp, 0, 0, IDTE_GLOBAL); __pmdp_idte(addr, pmdp, 0, 0, IDTE_GLOBAL);
if (mm_has_pgste(mm)) if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
gmap_pmdp_idte_global(mm, addr); gmap_pmdp_idte_global(mm, addr);
} else { } else {
__pmdp_csp(pmdp); __pmdp_csp(pmdp);
if (mm_has_pgste(mm)) if (mm_has_pgste(mm) && mm->context.allow_gmap_hpage_1m)
gmap_pmdp_csp(mm, addr); gmap_pmdp_csp(mm, addr);
} }
} }
......
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