Author: markj
Date: Thu Sep 20 15:45:12 2018
New Revision: 338830
URL: https://svnweb.freebsd.org/changeset/base/338830

Log:
  Change the domain selection policy in kmem_back().
  
  Ensure that pages backing the same virtual large page come from the
  same physical domain, as kmem_malloc_domain() does.
  
  PR:           231038
  Reviewed by:  alc, kib
  Approved by:  re (gjb)
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D17248

Modified:
  head/sys/vm/vm_kern.c

Modified: head/sys/vm/vm_kern.c
==============================================================================
--- head/sys/vm/vm_kern.c       Thu Sep 20 13:32:40 2018        (r338829)
+++ head/sys/vm/vm_kern.c       Thu Sep 20 15:45:12 2018        (r338830)
@@ -122,11 +122,12 @@ SYSCTL_ULONG(_vm, OID_AUTO, max_kernel_address, CTLFLA
     "Max kernel address");
 
 #if VM_NRESERVLEVEL > 0
-#define        KVA_QUANTUM     (1 << (VM_LEVEL_0_ORDER + PAGE_SHIFT))
+#define        KVA_QUANTUM_SHIFT       (VM_LEVEL_0_ORDER + PAGE_SHIFT)
 #else
 /* On non-superpage architectures want large import sizes. */
-#define        KVA_QUANTUM     (PAGE_SIZE * 1024)
+#define        KVA_QUANTUM_SHIFT       (10 + PAGE_SHIFT)
 #endif
+#define        KVA_QUANTUM             (1 << KVA_QUANTUM_SHIFT)
 
 /*
  *     kva_alloc:
@@ -416,9 +417,10 @@ kmem_malloc(vm_size_t size, int flags)
 }
 
 /*
- *     kmem_back:
+ *     kmem_back_domain:
  *
- *     Allocate physical pages for the specified virtual address range.
+ *     Allocate physical pages from the specified domain for the specified
+ *     virtual address range.
  */
 int
 kmem_back_domain(int domain, vm_object_t object, vm_offset_t addr,
@@ -479,24 +481,39 @@ retry:
        return (KERN_SUCCESS);
 }
 
+/*
+ *     kmem_back:
+ *
+ *     Allocate physical pages for the specified virtual address range.
+ */
 int
 kmem_back(vm_object_t object, vm_offset_t addr, vm_size_t size, int flags)
 {
-       struct vm_domainset_iter di;
-       int domain;
-       int ret;
+       vm_offset_t end, next, start;
+       int domain, rv;
 
        KASSERT(object == kernel_object,
            ("kmem_back: only supports kernel object."));
 
-       vm_domainset_iter_malloc_init(&di, kernel_object, &domain, &flags);
-       do {
-               ret = kmem_back_domain(domain, object, addr, size, flags);
-               if (ret == KERN_SUCCESS)
+       for (start = addr, end = addr + size; addr < end; addr = next) {
+               /*
+                * We must ensure that pages backing a given large virtual page
+                * all come from the same physical domain.
+                */
+               if (vm_ndomains > 1) {
+                       domain = (addr >> KVA_QUANTUM_SHIFT) % vm_ndomains;
+                       next = roundup2(addr + 1, KVA_QUANTUM);
+                       if (next > end || next < start)
+                               next = end;
+               } else
+                       next = end;
+               rv = kmem_back_domain(domain, object, addr, next - addr, flags);
+               if (rv != KERN_SUCCESS) {
+                       kmem_unback(object, start, addr - start);
                        break;
-       } while (vm_domainset_iter_malloc(&di, &domain, &flags) == 0);
-
-       return (ret);
+               }
+       }
+       return (rv);
 }
 
 /*
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to