Port-amd64 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

x86 page freelists



As noted on tech-kern@, i915drmkms requires allocating pages from
limited physical address ranges, and matt@ suggested using
UVM_PGA_STRAT_ONLY with VM_FREELIST_FIRST4G &c.  The constraints are
more limited than we have freelists for at the moment, so I would like
to add the following freelists to i386 and amd64,

VM_FREELIST_FIRST1T
VM_FREELIST_FIRST64G
VM_FREELIST_FIRST4G (i386 too, since we can have PAE)

and a routine x86_select_freelist(maxaddr) which returns the highest
freelist that maxaddr can fit into.  The attached patch implements
this, and gathers some of the logic of initx86_load_memmap into a
table and loops.

Comments?
Index: sys/arch/amd64/include/vmparam.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/vmparam.h,v
retrieving revision 1.34
diff -p -u -r1.34 vmparam.h
--- sys/arch/amd64/include/vmparam.h    25 Jan 2014 15:16:49 -0000      1.34
+++ sys/arch/amd64/include/vmparam.h    20 May 2014 23:10:31 -0000
@@ -157,10 +157,12 @@
 #define VM_PHYSSEG_MAX         32      /* 1 "hole" + 31 free lists */
 #define VM_PHYSSEG_STRAT       VM_PSTRAT_BIGFIRST
 
-#define        VM_NFREELIST            3
+#define        VM_NFREELIST            5
 #define        VM_FREELIST_DEFAULT     0
-#define        VM_FREELIST_FIRST4G     1
-#define        VM_FREELIST_FIRST16     2
+#define        VM_FREELIST_FIRST1T     1
+#define        VM_FREELIST_FIRST64G    2
+#define        VM_FREELIST_FIRST4G     3
+#define        VM_FREELIST_FIRST16     4
 
 #else  /*      !__x86_64__     */
 
Index: sys/arch/i386/include/vmparam.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/include/vmparam.h,v
retrieving revision 1.79
diff -p -u -r1.79 vmparam.h
--- sys/arch/i386/include/vmparam.h     28 Jan 2014 17:46:01 -0000      1.79
+++ sys/arch/i386/include/vmparam.h     20 May 2014 23:10:31 -0000
@@ -135,8 +135,9 @@
 #define        VM_NFREELIST            1
 #else
 #define        VM_PHYSSEG_MAX          32      /* 1 "hole" + 31 free lists */
-#define        VM_NFREELIST            2
-#define        VM_FREELIST_FIRST16     1
+#define        VM_NFREELIST            3
+#define        VM_FREELIST_FIRST16     2
+#define        VM_FREELIST_FIRST4G     1
 #endif /* XEN */
 #define        VM_FREELIST_DEFAULT     0
 
Index: sys/arch/x86/include/machdep.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/machdep.h,v
retrieving revision 1.6
diff -p -u -r1.6 machdep.h
--- sys/arch/x86/include/machdep.h      12 Apr 2013 16:59:41 -0000      1.6
+++ sys/arch/x86/include/machdep.h      20 May 2014 23:10:32 -0000
@@ -28,6 +28,8 @@
 #ifndef _X86_MACHDEP_H_
 #define _X86_MACHDEP_H_
 
+#include <sys/kcore.h>
+
 extern phys_ram_seg_t mem_clusters[];
 extern int mem_cluster_cnt;
 
@@ -42,6 +44,7 @@ void  x86_cpu_idle_set(void (*)(void), co
 int    initx86_parse_memmap(struct btinfo_memmap *, struct extent *);
 int    initx86_fake_memmap(struct extent *);
 int    initx86_load_memmap(paddr_t first_avail);
+int    x86_select_freelist(paddr_t);
 
 void   x86_startup(void);
 void   x86_sysctl_machdep_setup(struct sysctllog **);
Index: sys/arch/x86/x86/x86_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/x86_machdep.c,v
retrieving revision 1.64
diff -p -u -r1.64 x86_machdep.c
--- sys/arch/x86/x86/x86_machdep.c      1 Apr 2014 07:16:18 -0000       1.64
+++ sys/arch/x86/x86/x86_machdep.c      20 May 2014 23:10:32 -0000
@@ -686,44 +686,56 @@ extern vaddr_t kern_end;
 extern vaddr_t module_start, module_end;
 #endif
 
+static struct {
+       int freelist;
+       uint64_t limit;
+} x86_freelists[VM_NFREELIST] = {
+       { VM_FREELIST_DEFAULT, 0, },
+#ifdef VM_FREELIST_FIRST1T
+       /* 40-bit addresses needed for modern graphics.  */
+       { VM_FREELIST_FIRST1T,  1ULL * 1024 * 1024 * 1024 * 1024 },
+#endif
+#ifdef VM_FREELIST_FIRST64G
+       /* 36-bit addresses needed for oldish graphics.  */
+       { VM_FREELIST_FIRST64G, 64ULL * 1024 * 1024 * 1024 },
+#endif
+#ifdef VM_FREELIST_FIRST4G
+       /* 32-bit addresses needed for PCI 32-bit DMA and old graphics.  */
+       { VM_FREELIST_FIRST4G,  4ULL * 1024 * 1024 * 1024 },
+#endif
+       /* 24-bit addresses needed for ISA DMA and ancient graphics.  */
+       { VM_FREELIST_FIRST16,  16 * 1024 * 1024 },
+};
+
+int
+x86_select_freelist(uint64_t maxaddr)
+{
+       unsigned int i;
+
+       for (i = 0; i < __arraycount(x86_freelists); i++) {
+               printf("%s %u freelist %d limit %"PRIx64" maxaddr %"PRIx64"\n",
+                   __func__, i,
+                   x86_freelists[i].freelist, x86_freelists[i].limit,
+                   maxaddr);
+               if ((x86_freelists[i].limit - 1) <= maxaddr)
+                       return x86_freelists[i].freelist;
+       }
+
+       panic("no freelist for maximum address %"PRIx64, maxaddr);
+}
+
 int
 initx86_load_memmap(paddr_t first_avail)
 {
        uint64_t seg_start, seg_end;
        uint64_t seg_start1, seg_end1;
-       int first16q, x;
-#ifdef VM_FREELIST_FIRST4G
-       int first4gq;
-#endif
-
-       /*
-        * If we have 16M of RAM or less, just put it all on
-        * the default free list.  Otherwise, put the first
-        * 16M of RAM on a lower priority free list (so that
-        * all of the ISA DMA'able memory won't be eaten up
-        * first-off).
-        */
-#define ADDR_16M (16 * 1024 * 1024)
-
-       if (avail_end <= ADDR_16M)
-               first16q = VM_FREELIST_DEFAULT;
-       else
-               first16q = VM_FREELIST_FIRST16;
+       int x;
+       unsigned i;
 
-#ifdef VM_FREELIST_FIRST4G
-       /*
-        * If we have 4G of RAM or less, just put it all on
-        * the default free list.  Otherwise, put the first
-        * 4G of RAM on a lower priority free list (so that
-        * all of the 32bit PCI DMA'able memory won't be eaten up
-        * first-off).
-        */
-#define ADDR_4G (4ULL * 1024 * 1024 * 1024)
-       if (avail_end <= ADDR_4G)
-               first4gq = VM_FREELIST_DEFAULT;
-       else
-               first4gq = VM_FREELIST_FIRST4G;
-#endif /* defined(VM_FREELIST_FIRST4G) */
+       for (i = 0; i < __arraycount(x86_freelists); i++) {
+               if (avail_end < x86_freelists[i].limit)
+                       x86_freelists[i].freelist = VM_FREELIST_DEFAULT;
+       }
 
        /* Make sure the end of the space used by the kernel is rounded. */
        first_avail = round_page(first_avail);
@@ -776,57 +788,31 @@ initx86_load_memmap(paddr_t first_avail)
 
                /* First hunk */
                if (seg_start != seg_end) {
-                       if (seg_start < ADDR_16M &&
-                           first16q != VM_FREELIST_DEFAULT) {
+                       i = __arraycount(x86_freelists);
+                       while (i--) {
                                uint64_t tmp;
 
-                               if (seg_end > ADDR_16M)
-                                       tmp = ADDR_16M;
-                               else
-                                       tmp = seg_end;
-
-                               if (tmp != seg_start) {
+                               if (x86_freelists[i].limit <= seg_start)
+                                       continue;
+                               if (x86_freelists[i].freelist ==
+                                   VM_FREELIST_DEFAULT)
+                                       continue;
+                               tmp = MIN(x86_freelists[i].limit, seg_end);
+                               if (tmp == seg_start)
+                                       continue;
 #ifdef DEBUG_MEMLOAD
-                                       printf("loading first16q 0x%"PRIx64
-                                           "-0x%"PRIx64
-                                           " (0x%"PRIx64"-0x%"PRIx64")\n",
-                                           seg_start, tmp,
-                                           (uint64_t)atop(seg_start),
-                                           (uint64_t)atop(tmp));
-#endif
-                                       uvm_page_physload(atop(seg_start),
-                                           atop(tmp), atop(seg_start),
-                                           atop(tmp), first16q);
-                               }
-                               seg_start = tmp;
-                       }
-
-#ifdef VM_FREELIST_FIRST4G
-                       if (seg_start < ADDR_4G &&
-                           first4gq != VM_FREELIST_DEFAULT) {
-                               uint64_t tmp;
-
-                               if (seg_end > ADDR_4G)
-                                       tmp = ADDR_4G;
-                               else
-                                       tmp = seg_end;
-
-                               if (tmp != seg_start) {
-#ifdef DEBUG_MEMLOAD
-                                       printf("loading first4gq 0x%"PRIx64
-                                           "-0x%"PRIx64
-                                           " (0x%"PRIx64"-0x%"PRIx64")\n",
-                                           seg_start, tmp,
-                                           (uint64_t)atop(seg_start),
-                                           (uint64_t)atop(tmp));
-#endif
-                                       uvm_page_physload(atop(seg_start),
-                                           atop(tmp), atop(seg_start),
-                                           atop(tmp), first4gq);
-                               }
+                               printf("loading freelist %d"
+                                   " 0x%"PRIx64"-0x%"PRIx64
+                                   " (0x%"PRIx64"-0x%"PRIx64")\n",
+                                   x86_freelists[i].freelist, seg_start, tmp,
+                                   (uint64_t)atop(seg_start),
+                                   (uint64_t)atop(tmp));
+#endif
+                               uvm_page_physload(atop(seg_start), atop(tmp),
+                                   atop(seg_start), atop(tmp),
+                                   x86_freelists[i].freelist);
                                seg_start = tmp;
                        }
-#endif /* defined(VM_FREELIST_FIRST4G) */
 
                        if (seg_start != seg_end) {
 #ifdef DEBUG_MEMLOAD
@@ -844,57 +830,31 @@ initx86_load_memmap(paddr_t first_avail)
 
                /* Second hunk */
                if (seg_start1 != seg_end1) {
-                       if (seg_start1 < ADDR_16M &&
-                           first16q != VM_FREELIST_DEFAULT) {
-                               uint64_t tmp;
-
-                               if (seg_end1 > ADDR_16M)
-                                       tmp = ADDR_16M;
-                               else
-                                       tmp = seg_end1;
-
-                               if (tmp != seg_start1) {
-#ifdef DEBUG_MEMLOAD
-                                       printf("loading first16q 0x%"PRIx64
-                                           "-0x%"PRIx64
-                                           " (0x%"PRIx64"-0x%"PRIx64")\n",
-                                           seg_start1, tmp,
-                                           (uint64_t)atop(seg_start1),
-                                           (uint64_t)atop(tmp));
-#endif
-                                       uvm_page_physload(atop(seg_start1),
-                                           atop(tmp), atop(seg_start1),
-                                           atop(tmp), first16q);
-                               }
-                               seg_start1 = tmp;
-                       }
-
-#ifdef VM_FREELIST_FIRST4G
-                       if (seg_start1 < ADDR_4G &&
-                           first4gq != VM_FREELIST_DEFAULT) {
+                       i = __arraycount(x86_freelists);
+                       while (i--) {
                                uint64_t tmp;
 
-                               if (seg_end1 > ADDR_4G)
-                                       tmp = ADDR_4G;
-                               else
-                                       tmp = seg_end1;
-
-                               if (tmp != seg_start1) {
+                               if (x86_freelists[i].limit <= seg_start1)
+                                       continue;
+                               if (x86_freelists[i].freelist ==
+                                   VM_FREELIST_DEFAULT)
+                                       continue;
+                               tmp = MIN(x86_freelists[i].limit, seg_end1);
+                               if (tmp == seg_start1)
+                                       continue;
 #ifdef DEBUG_MEMLOAD
-                                       printf("loading first4gq 0x%"PRIx64
-                                           "-0x%"PRIx64
-                                           " (0x%"PRIx64"-0x%"PRIx64")\n",
-                                           seg_start1, tmp,
-                                           (uint64_t)atop(seg_start1),
-                                           (uint64_t)atop(tmp));
-#endif
-                                       uvm_page_physload(atop(seg_start1),
-                                           atop(tmp), atop(seg_start1),
-                                           atop(tmp), first4gq);
-                               }
+                               printf("loading freelist %d"
+                                   " 0x%"PRIx64"-0x%"PRIx64
+                                   " (0x%"PRIx64"-0x%"PRIx64")\n",
+                                   x86_freelists[i].freelist, seg_start1, tmp,
+                                   (uint64_t)atop(seg_start1),
+                                   (uint64_t)atop(tmp));
+#endif
+                               uvm_page_physload(atop(seg_start1), atop(tmp),
+                                   atop(seg_start1), atop(tmp),
+                                   x86_freelists[i].freelist);
                                seg_start1 = tmp;
                        }
-#endif /* defined(VM_FREELIST_FIRST4G) */
 
                        if (seg_start1 != seg_end1) {
 #ifdef DEBUG_MEMLOAD


Home | Main Index | Thread Index | Old Index