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