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