Module Name:    src
Committed By:   riastradh
Date:           Thu Jun 12 19:02:35 UTC 2014

Modified Files:
        src/sys/arch/amd64/include: vmparam.h
        src/sys/arch/i386/include: vmparam.h
        src/sys/arch/x86/include: machdep.h
        src/sys/arch/x86/x86: x86_machdep.c

Log Message:
Tweak x86 page freelists and add x86_select_freelist.

- Add 4G freelist to i386 -- there may be higher addresses if PAE.
- Add 64G and 1T freelists to amd64.
- Simplify freelist setup code and condense it into a table.
- Add x86_select_freelist to get a freelist guaranteed to yield
addresses no greater than a prescribed maximum address.

x86_select_freelist takes a uint64_t, not a paddr_t or bus_addr_t, so
that you can pass in, e.g., a 36-bit maximum address without needing
to write conditionals for i386/PAE.

No objections on port-x86:

https://mail-index.netbsd.org/port-i386/2014/05/21/msg003277.html
https://mail-index.netbsd.org/port-amd64/2014/05/21/msg002062.html


To generate a diff of this commit:
cvs rdiff -u -r1.34 -r1.35 src/sys/arch/amd64/include/vmparam.h
cvs rdiff -u -r1.79 -r1.80 src/sys/arch/i386/include/vmparam.h
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/x86/include/machdep.h
cvs rdiff -u -r1.64 -r1.65 src/sys/arch/x86/x86/x86_machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/include/vmparam.h
diff -u src/sys/arch/amd64/include/vmparam.h:1.34 src/sys/arch/amd64/include/vmparam.h:1.35
--- src/sys/arch/amd64/include/vmparam.h:1.34	Sat Jan 25 15:16:49 2014
+++ src/sys/arch/amd64/include/vmparam.h	Thu Jun 12 19:02:35 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmparam.h,v 1.34 2014/01/25 15:16:49 christos Exp $	*/
+/*	$NetBSD: vmparam.h,v 1.35 2014/06/12 19:02:35 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -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: src/sys/arch/i386/include/vmparam.h
diff -u src/sys/arch/i386/include/vmparam.h:1.79 src/sys/arch/i386/include/vmparam.h:1.80
--- src/sys/arch/i386/include/vmparam.h:1.79	Tue Jan 28 17:46:01 2014
+++ src/sys/arch/i386/include/vmparam.h	Thu Jun 12 19:02:35 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: vmparam.h,v 1.79 2014/01/28 17:46:01 christos Exp $	*/
+/*	$NetBSD: vmparam.h,v 1.80 2014/06/12 19:02:35 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -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: src/sys/arch/x86/include/machdep.h
diff -u src/sys/arch/x86/include/machdep.h:1.6 src/sys/arch/x86/include/machdep.h:1.7
--- src/sys/arch/x86/include/machdep.h:1.6	Fri Apr 12 16:59:41 2013
+++ src/sys/arch/x86/include/machdep.h	Thu Jun 12 19:02:35 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.h,v 1.6 2013/04/12 16:59:41 christos Exp $ */
+/* $NetBSD: machdep.h,v 1.7 2014/06/12 19:02:35 riastradh Exp $ */
 /*
  * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -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(uint64_t);
 
 void	x86_startup(void);
 void	x86_sysctl_machdep_setup(struct sysctllog **);

Index: src/sys/arch/x86/x86/x86_machdep.c
diff -u src/sys/arch/x86/x86/x86_machdep.c:1.64 src/sys/arch/x86/x86/x86_machdep.c:1.65
--- src/sys/arch/x86/x86/x86_machdep.c:1.64	Tue Apr  1 07:16:18 2014
+++ src/sys/arch/x86/x86/x86_machdep.c	Thu Jun 12 19:02:35 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_machdep.c,v 1.64 2014/04/01 07:16:18 dsl Exp $	*/
+/*	$NetBSD: x86_machdep.c,v 1.65 2014/06/12 19:02:35 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.64 2014/04/01 07:16:18 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.65 2014/06/12 19:02:35 riastradh Exp $");
 
 #include "opt_modular.h"
 #include "opt_physmem.h"
@@ -686,44 +686,55 @@ 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;
+
+	if (avail_end <= maxaddr)
+		return VM_NFREELIST;
+
+	for (i = 0; i < __arraycount(x86_freelists); i++) {
+		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 +787,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) {
-#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) {
+				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 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 +829,31 @@ initx86_load_memmap(paddr_t first_avail)
 
 		/* Second hunk */
 		if (seg_start1 != seg_end1) {
-			if (seg_start1 < ADDR_16M &&
-			    first16q != VM_FREELIST_DEFAULT) {
+			i = __arraycount(x86_freelists);
+			while (i--) {
 				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) {
-				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 %u"
+				    " 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

Reply via email to