diff options
author | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2010-06-27 03:03:50 +0000 |
---|---|---|
committer | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2010-06-27 03:03:50 +0000 |
commit | 8a46d785199bcae03d0469a55b99e08fe33263fa (patch) | |
tree | 9b784b445528b5c78da12077fd065ae9030cf6d7 | |
parent | b109c783d06f4af76ff573fa020fbe9d1d855f7b (diff) |
uvm constraints. Add two mandatory MD symbols, uvm_md_constraints
which contains the constraints for DMA/memory allocation for each
architecture, and dma_constraints which contains the range of addresses
that are dma accessable by the system.
This is based on ariane@'s physcontig diff, with lots of bugfixes and
additions the following additions by my self:
Introduce a new function pool_set_constraints() which sets the address
range for which we allocate pages for the pool from, this is now used
for the mbuf/mbuf cluster pools to keep them dma accessible.
The !direct archs no longer stuff pages into the kernel object in
uvm_km_getpage_pla but rather do a pmap_extract() in uvm_km_putpages.
Tested heavily by my self on i386, amd64 and sparc64. Some tests on
alpha and SGI.
"commit it" beck, art, oga, deraadt
"i like the diff" deraadt
35 files changed, 461 insertions, 238 deletions
diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c index 0f43e75e31f..ed2a1f98fd3 100644 --- a/sys/arch/alpha/alpha/machdep.c +++ b/sys/arch/alpha/alpha/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.123 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.124 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */ /*- @@ -143,6 +143,13 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL }; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { + &isa_constraint, + NULL +}; + struct vm_map *exec_map = NULL; struct vm_map *phys_map = NULL; diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index bbdf79e4ded..68bb5bc526b 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.111 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.112 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- @@ -94,6 +94,7 @@ #include <dev/cons.h> #include <stand/boot/bootarg.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <uvm/uvm_page.h> #include <uvm/uvm_swap.h> @@ -207,6 +208,15 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +/* UVM constraint ranges. */ +struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL }; +struct uvm_constraint_range dma_constraint = { 0x0, 0xffffffffUL }; +struct uvm_constraint_range *uvm_md_constraints[] = { + &isa_constraint, + &dma_constraint, + NULL, +}; + #ifdef DEBUG int sigdebug = 0; pid_t sigpid = 0; diff --git a/sys/arch/arm/arm/arm32_machdep.c b/sys/arch/arm/arm/arm32_machdep.c index b90be48c651..d3e6e5b96e3 100644 --- a/sys/arch/arm/arm/arm32_machdep.c +++ b/sys/arch/arm/arm/arm32_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: arm32_machdep.c,v 1.33 2010/06/09 15:44:17 miod Exp $ */ +/* $OpenBSD: arm32_machdep.c,v 1.34 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: arm32_machdep.c,v 1.42 2003/12/30 12:33:15 pk Exp $ */ /* @@ -54,6 +54,7 @@ #include <sys/msg.h> #include <sys/msgbuf.h> #include <sys/device.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <sys/sysctl.h> @@ -86,6 +87,9 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + int cold = 1; pv_addr_t kernelstack; diff --git a/sys/arch/armish/armish/armish_machdep.c b/sys/arch/armish/armish/armish_machdep.c index cc818b5b826..399cd56e14f 100644 --- a/sys/arch/armish/armish/armish_machdep.c +++ b/sys/arch/armish/armish/armish_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: armish_machdep.c,v 1.14 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: armish_machdep.c,v 1.15 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: lubbock_machdep.c,v 1.2 2003/07/15 00:25:06 lukem Exp $ */ /* @@ -91,6 +91,7 @@ #include <sys/termios.h> #include <sys/kcore.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <sys/conf.h> @@ -175,6 +176,9 @@ pv_addr_t minidataclean; paddr_t msgbufphys; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + extern u_int data_abort_handler_address; extern u_int prefetch_abort_handler_address; extern u_int undefined_handler_address; diff --git a/sys/arch/aviion/aviion/machdep.c b/sys/arch/aviion/aviion/machdep.c index 4d58c533bb5..9c01103039a 100644 --- a/sys/arch/aviion/aviion/machdep.c +++ b/sys/arch/aviion/aviion/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.37 2010/04/24 18:46:51 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.38 2010/06/27 03:03:48 thib Exp $ */ /* * Copyright (c) 2007 Miodrag Vallat. * @@ -148,6 +148,9 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + /* * Info for CTL_HW */ diff --git a/sys/arch/beagle/beagle/beagle_machdep.c b/sys/arch/beagle/beagle/beagle_machdep.c index cdf623921c9..9b2952d8256 100644 --- a/sys/arch/beagle/beagle/beagle_machdep.c +++ b/sys/arch/beagle/beagle/beagle_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: beagle_machdep.c,v 1.4 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: beagle_machdep.c,v 1.5 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: lubbock_machdep.c,v 1.2 2003/07/15 00:25:06 lukem Exp $ */ /* @@ -122,6 +122,7 @@ #include <sys/reboot.h> #include <sys/termios.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <sys/conf.h> @@ -207,6 +208,9 @@ pv_addr_t minidataclean; vaddr_t msgbufphys; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + extern u_int data_abort_handler_address; extern u_int prefetch_abort_handler_address; extern u_int undefined_handler_address; diff --git a/sys/arch/gumstix/gumstix/gumstix_machdep.c b/sys/arch/gumstix/gumstix/gumstix_machdep.c index a3e278b83df..43edb526dcb 100644 --- a/sys/arch/gumstix/gumstix/gumstix_machdep.c +++ b/sys/arch/gumstix/gumstix/gumstix_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gumstix_machdep.c,v 1.2 2009/07/26 18:48:55 miod Exp $ */ +/* $OpenBSD: gumstix_machdep.c,v 1.3 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: lubbock_machdep.c,v 1.2 2003/07/15 00:25:06 lukem Exp $ */ /* @@ -239,6 +239,9 @@ pv_addr_t kernel_pt_table[NUM_KERNEL_PTS]; extern struct user *proc0paddr; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + /* Prototypes */ #define BOOT_STRING_MAGIC 0x4f425344 diff --git a/sys/arch/hp300/hp300/machdep.c b/sys/arch/hp300/hp300/machdep.c index 9e7f020213f..bec60a33c4d 100644 --- a/sys/arch/hp300/hp300/machdep.c +++ b/sys/arch/hp300/hp300/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.126 2009/08/11 19:17:16 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.127 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.121 1999/03/26 23:41:29 mycroft Exp $ */ /* @@ -114,6 +114,10 @@ int bufpages = 0; int bufcachepercent = BUFCACHEPERCENT; int physmem; /* size of physical memory, in pages */ + +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c index c2a74de56ea..2cc6fe47640 100644 --- a/sys/arch/hppa/hppa/machdep.c +++ b/sys/arch/hppa/hppa/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.188 2010/06/27 00:04:44 jsing Exp $ */ +/* $OpenBSD: machdep.c,v 1.189 2010/06/27 03:03:48 thib Exp $ */ /* * Copyright (c) 1999-2003 Michael Shalayeff @@ -202,6 +202,9 @@ pid_t sigpid = 0; #define SDB_FOLLOW 0x01 #endif +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + /* * Whatever CPU types we support */ diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 2bf83682dc7..aa57e7c8821 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.473 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.474 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -195,6 +195,14 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL }; +struct uvm_constraint_range dma_constraint = { 0x0, 0xffffffffUL }; +struct uvm_constraint_range *uvm_md_constraints[] = { + &isa_constraint, + &dma_constraint, + NULL +}; + extern int boothowto; int physmem; diff --git a/sys/arch/landisk/landisk/machdep.c b/sys/arch/landisk/landisk/machdep.c index fb083fc9b62..23f01445da0 100644 --- a/sys/arch/landisk/landisk/machdep.c +++ b/sys/arch/landisk/landisk/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.21 2010/06/26 23:24:43 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.22 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.1 2006/09/01 21:26:18 uwe Exp $ */ /*- @@ -115,6 +115,9 @@ int led_blink; extern u_int32_t getramsize(void); +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git a/sys/arch/loongson/loongson/machdep.c b/sys/arch/loongson/loongson/machdep.c index 95f32216b09..9bb545d41f5 100644 --- a/sys/arch/loongson/loongson/machdep.c +++ b/sys/arch/loongson/loongson/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.20 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.21 2010/06/27 03:03:48 thib Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -94,6 +94,14 @@ char pmon_bootp[80]; int bufpages = BUFPAGES; int bufcachepercent = BUFCACHEPERCENT; +/* + * Even though the system is 64bit, the hardware is constrained to up + * to 2G of contigous physical memory (direct 2GB DMA area), so there + * is no particular constraint. paddr_t is long so: + */ +struct uvm_constraint_range dma_constraint = { 0x0, 0xffffffffUL }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + vm_map_t exec_map; vm_map_t phys_map; diff --git a/sys/arch/luna88k/luna88k/machdep.c b/sys/arch/luna88k/luna88k/machdep.c index 20425fae49f..3e37e07e8a0 100644 --- a/sys/arch/luna88k/luna88k/machdep.c +++ b/sys/arch/luna88k/luna88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.70 2010/06/09 15:44:17 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.71 2010/06/27 03:03:48 thib Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -197,6 +197,9 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + /* * Info for CTL_HW */ diff --git a/sys/arch/mac68k/mac68k/machdep.c b/sys/arch/mac68k/mac68k/machdep.c index 384485b82aa..22622ab2289 100644 --- a/sys/arch/mac68k/mac68k/machdep.c +++ b/sys/arch/mac68k/mac68k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.153 2009/08/11 19:17:16 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.154 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.207 1998/07/08 04:39:34 thorpej Exp $ */ /* @@ -184,6 +184,9 @@ int bufcachepercent = BUFCACHEPERCENT; int physmem; /* size of physical memory, in pages */ +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git a/sys/arch/macppc/macppc/machdep.c b/sys/arch/macppc/macppc/machdep.c index ec714434d25..44cd0be02a6 100644 --- a/sys/arch/macppc/macppc/machdep.c +++ b/sys/arch/macppc/macppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.117 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.118 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -52,6 +52,7 @@ #include <sys/core.h> #include <sys/kcore.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <dev/cons.h> @@ -106,6 +107,9 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + struct bat battable[16]; struct vm_map *exec_map = NULL; diff --git a/sys/arch/mvme68k/mvme68k/machdep.c b/sys/arch/mvme68k/mvme68k/machdep.c index c61381d1a69..eb245c57da6 100644 --- a/sys/arch/mvme68k/mvme68k/machdep.c +++ b/sys/arch/mvme68k/mvme68k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.120 2009/08/11 19:17:16 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.121 2010/06/27 03:03:48 thib Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -141,6 +141,10 @@ int bufpages = 0; int bufcachepercent = BUFCACHEPERCENT; int physmem; /* size of physical memory, in pages */ + +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index 9ae417ec3e5..90b9bb0aee4 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.235 2009/08/11 19:17:16 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.236 2010/06/27 03:03:48 thib Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -162,6 +162,13 @@ int bufpages = 0; int bufcachepercent = BUFCACHEPERCENT; /* + * 32 or 34 bit physical address bus depending upon the CPU flavor. + * 32 bit DMA. "I am not aware of any system where the upper 2 bits + * have ever been used" - miod@ +struct uvm_constraint_range dma_constraint = { 0x0, 0xffffffffUL}; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + +/* * Info for CTL_HW */ char machine[] = MACHINE; /* cpu "architecture" */ diff --git a/sys/arch/palm/palm/palm_machdep.c b/sys/arch/palm/palm/palm_machdep.c index 2fb6cc3e176..5b3700a44a3 100644 --- a/sys/arch/palm/palm/palm_machdep.c +++ b/sys/arch/palm/palm/palm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: palm_machdep.c,v 1.3 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: palm_machdep.c,v 1.4 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: lubbock_machdep.c,v 1.2 2003/07/15 00:25:06 lukem Exp $ */ /* @@ -123,6 +123,7 @@ #include <sys/termios.h> #include <sys/kcore.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <sys/conf.h> @@ -213,6 +214,9 @@ pv_addr_t minidataclean; paddr_t msgbufphys; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + extern u_int data_abort_handler_address; extern u_int prefetch_abort_handler_address; extern u_int undefined_handler_address; diff --git a/sys/arch/sgi/sgi/machdep.c b/sys/arch/sgi/sgi/machdep.c index 5510a7b6d3c..14742f0e9c4 100644 --- a/sys/arch/sgi/sgi/machdep.c +++ b/sys/arch/sgi/sgi/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.103 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.104 2010/06/27 03:03:48 thib Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -47,6 +47,7 @@ #include <sys/sem.h> #endif +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <machine/db_machdep.h> @@ -95,6 +96,10 @@ char cpu_model[30]; int bufpages = BUFPAGES; int bufcachepercent = BUFCACHEPERCENT; +/* low 32 bits range. */ +struct uvm_constraint_range dma_constraint = { 0x0, 0x7fffffff }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + vm_map_t exec_map; vm_map_t phys_map; diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c index c1bdc1d4b61..9e0aec76061 100644 --- a/sys/arch/socppc/socppc/machdep.c +++ b/sys/arch/socppc/socppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.24 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.25 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -48,6 +48,7 @@ #include <sys/tty.h> #include <sys/user.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <machine/bat.h> @@ -85,6 +86,9 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + struct bat battable[16]; struct vm_map *exec_map = NULL; diff --git a/sys/arch/sparc/include/vmparam.h b/sys/arch/sparc/include/vmparam.h index a7ba9e169b3..53a6ba9c401 100644 --- a/sys/arch/sparc/include/vmparam.h +++ b/sys/arch/sparc/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.34 2010/04/22 19:02:47 oga Exp $ */ +/* $OpenBSD: vmparam.h,v 1.35 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: vmparam.h,v 1.13 1997/07/12 16:20:03 perry Exp $ */ /* @@ -130,9 +130,6 @@ struct vm_page_md { #define VM_NFREELIST 1 #define VM_FREELIST_DEFAULT 0 -/* No UVM_IO_RANGES required: IOMMU takes care of this. */ -#define UVM_IO_RANGES {} - #if defined (_KERNEL) && !defined(_LOCORE) struct vm_map; #define dvma_mapin(map,va,len,canwait) dvma_mapin_space(map,va,len,canwait,0) diff --git a/sys/arch/sparc/sparc/machdep.c b/sys/arch/sparc/sparc/machdep.c index 3ee479bbd41..d1543fe59e8 100644 --- a/sys/arch/sparc/sparc/machdep.c +++ b/sys/arch/sparc/sparc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.124 2009/08/29 15:27:33 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.125 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.85 1997/09/12 08:55:02 pk Exp $ */ /* @@ -119,6 +119,9 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + int physmem; /* sysctl settable */ diff --git a/sys/arch/sparc64/include/vmparam.h b/sys/arch/sparc64/include/vmparam.h index b3eca0ba6a4..3d9e6d8fad8 100644 --- a/sys/arch/sparc64/include/vmparam.h +++ b/sys/arch/sparc64/include/vmparam.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmparam.h,v 1.19 2010/04/22 19:02:49 oga Exp $ */ +/* $OpenBSD: vmparam.h,v 1.20 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: vmparam.h,v 1.18 2001/05/01 02:19:19 thorpej Exp $ */ /* @@ -145,9 +145,6 @@ #define VM_NFREELIST 1 #define VM_FREELIST_DEFAULT 0 -/* No UVM_IO_RANGES required: IOMMU takes care of this. */ -#define UVM_IO_RANGES {} - #define __HAVE_VM_PAGE_MD /* * For each struct vm_page, there is a list of all currently valid virtual diff --git a/sys/arch/sparc64/sparc64/machdep.c b/sys/arch/sparc64/sparc64/machdep.c index 4e60b5d04de..0a0d305b8d8 100644 --- a/sys/arch/sparc64/sparc64/machdep.c +++ b/sys/arch/sparc64/sparc64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.123 2010/03/29 19:21:58 oga Exp $ */ +/* $OpenBSD: machdep.c,v 1.124 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: machdep.c,v 1.108 2001/07/24 19:30:14 eeh Exp $ */ /*- @@ -175,6 +175,9 @@ int bufpages = 0; #endif int bufcachepercent = BUFCACHEPERCENT; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + int physmem; extern caddr_t msgbufaddr; diff --git a/sys/arch/zaurus/zaurus/zaurus_machdep.c b/sys/arch/zaurus/zaurus/zaurus_machdep.c index 09ac248fece..622079282c0 100644 --- a/sys/arch/zaurus/zaurus/zaurus_machdep.c +++ b/sys/arch/zaurus/zaurus/zaurus_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: zaurus_machdep.c,v 1.33 2010/06/10 17:54:13 deraadt Exp $ */ +/* $OpenBSD: zaurus_machdep.c,v 1.34 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: lubbock_machdep.c,v 1.2 2003/07/15 00:25:06 lukem Exp $ */ /* @@ -123,6 +123,7 @@ #include <sys/termios.h> #include <sys/kcore.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> #include <sys/conf.h> @@ -221,6 +222,9 @@ pv_addr_t minidataclean; paddr_t msgbufphys; +struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; +struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; + extern u_int data_abort_handler_address; extern u_int prefetch_abort_handler_address; extern u_int undefined_handler_address; diff --git a/sys/kern/subr_pool.c b/sys/kern/subr_pool.c index ba56aaf367e..a8c7771c468 100644 --- a/sys/kern/subr_pool.c +++ b/sys/kern/subr_pool.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_pool.c,v 1.92 2010/06/17 16:11:20 miod Exp $ */ +/* $OpenBSD: subr_pool.c,v 1.93 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: subr_pool.c,v 1.61 2001/09/26 07:14:56 chs Exp $ */ /*- @@ -94,6 +94,12 @@ struct pool_item { ((pp)->pr_nitems < (pp)->pr_minitems) /* + * Default constraint range for pools, that cover the whole + * address space. + */ +struct uvm_constraint_range pool_full_range = { 0x0, (paddr_t)-1 }; + +/* * Every pool gets a unique serial number assigned to it. If this counter * wraps, we're screwed, but we shouldn't create so many pools anyway. */ @@ -393,6 +399,10 @@ pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags, pool_setipl(&phpool, IPL_HIGH); } + /* pglistalloc/constraint parameters */ + pp->pr_crange = &pool_full_range; + pp->pr_pa_nsegs = 0; + /* Insert this into the list of all pools. */ TAILQ_INSERT_HEAD(&pool_head, pp, pr_poollist); } @@ -999,6 +1009,21 @@ done: } void +pool_set_constraints(struct pool *pp, struct uvm_constraint_range *range, + int nsegs) +{ + /* + * Subsequent changes to the constrictions are only + * allowed to make them _more_ strict. + */ + KASSERT(pp->pr_crange->ucr_high >= range->ucr_high && + pp->pr_crange->ucr_low <= range->ucr_low); + + pp->pr_crange = range; + pp->pr_pa_nsegs = nsegs; +} + +void pool_set_ctordtor(struct pool *pp, int (*ctor)(void *, void *, int), void (*dtor)(void *, void *), void *arg) { @@ -1452,15 +1477,15 @@ pool_allocator_free(struct pool *pp, void *v) void * pool_page_alloc(struct pool *pp, int flags, int *slowdown) { - boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE; + int kfl = (flags & PR_WAITOK) ? 0 : UVM_KMF_NOWAIT; - return (uvm_km_getpage(waitok, slowdown)); + return (uvm_km_getpage_pla(kfl, slowdown, pp->pr_crange->ucr_low, + pp->pr_crange->ucr_high, 0, 0)); } void pool_page_free(struct pool *pp, void *v) { - uvm_km_putpage(v); } @@ -1472,7 +1497,9 @@ pool_large_alloc(struct pool *pp, int flags, int *slowdown) int s; s = splvm(); - va = uvm_km_kmemalloc(kmem_map, NULL, pp->pr_alloc->pa_pagesz, kfl); + va = uvm_km_kmemalloc_pla(kmem_map, NULL, pp->pr_alloc->pa_pagesz, kfl, + pp->pr_crange->ucr_low, pp->pr_crange->ucr_high, + 0, 0, pp->pr_pa_nsegs); splx(s); return ((void *)va); @@ -1493,8 +1520,10 @@ pool_large_alloc_ni(struct pool *pp, int flags, int *slowdown) { int kfl = (flags & PR_WAITOK) ? 0 : UVM_KMF_NOWAIT; - return ((void *)uvm_km_kmemalloc(kernel_map, uvm.kernel_object, - pp->pr_alloc->pa_pagesz, kfl)); + return ((void *)uvm_km_kmemalloc_pla(kernel_map, uvm.kernel_object, + pp->pr_alloc->pa_pagesz, kfl, + pp->pr_crange->ucr_low, pp->pr_crange->ucr_high, + 0, 0, pp->pr_pa_nsegs)); } void diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index a7033c1ddb4..99c1decbb06 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.137 2010/06/07 19:47:25 blambert Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.138 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -90,6 +90,7 @@ #include <machine/cpu.h> +#include <uvm/uvm.h> #include <uvm/uvm_extern.h> struct mbstat mbstat; /* mbuf stats */ @@ -137,13 +138,15 @@ mbinit(void) pool_init(&mbpool, MSIZE, 0, 0, 0, "mbpl", NULL); pool_setlowat(&mbpool, mblowat); + pool_set_constraints(&mbpool, &dma_constraint, 1); for (i = 0; i < nitems(mclsizes); i++) { snprintf(mclnames[i], sizeof(mclnames[0]), "mcl%dk", mclsizes[i] >> 10); - pool_init(&mclpools[i], mclsizes[i], 0, 0, 0, mclnames[i], - NULL); + pool_init(&mclpools[i], mclsizes[i], 0, 0, 0, + mclnames[i], NULL); pool_setlowat(&mclpools[i], mcllowat); + pool_set_constraints(&mclpools[i], &dma_constraint, 1); } nmbclust_update(); diff --git a/sys/sys/pool.h b/sys/sys/pool.h index 94360d43224..e49d075d407 100644 --- a/sys/sys/pool.h +++ b/sys/sys/pool.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pool.h,v 1.33 2009/08/13 13:49:20 thib Exp $ */ +/* $OpenBSD: pool.h,v 1.34 2010/06/27 03:03:48 thib Exp $ */ /* $NetBSD: pool.h,v 1.27 2001/06/06 22:00:17 rafal Exp $ */ /*- @@ -131,6 +131,10 @@ struct pool { unsigned long pr_npagefree; /* # of pages released */ unsigned int pr_hiwat; /* max # of pages in pool */ unsigned long pr_nidle; /* # of idle pages */ + + /* Physical memory configuration. */ + struct uvm_constraint_range *pr_crange; + int pr_pa_nsegs; }; #ifdef _KERNEL @@ -144,6 +148,9 @@ void pool_setipl(struct pool *, int); void pool_setlowat(struct pool *, int); void pool_sethiwat(struct pool *, int); int pool_sethardlimit(struct pool *, u_int, const char *, int); +struct uvm_constraint_range; /* XXX */ +void pool_set_constraints(struct pool *, + struct uvm_constraint_range *, int); void pool_set_ctordtor(struct pool *, int (*)(void *, void *, int), void(*)(void *, void *), void *); diff --git a/sys/uvm/uvm.h b/sys/uvm/uvm.h index 9814120fd39..258a16c8f3c 100644 --- a/sys/uvm/uvm.h +++ b/sys/uvm/uvm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm.h,v 1.39 2010/06/09 08:26:21 thib Exp $ */ +/* $OpenBSD: uvm.h,v 1.40 2010/06/27 03:03:49 thib Exp $ */ /* $NetBSD: uvm.h,v 1.24 2000/11/27 08:40:02 chs Exp $ */ /* @@ -68,33 +68,28 @@ #include <machine/vmparam.h> /* - * UVM_IO_RANGES: paddr_t pairs, describing the lowest and highest address - * that should be reserved. These ranges (which may overlap) will have their - * use counter increased, causing them to be avoided if an allocation can be - * satisfied from another range of memory. + * uvm_constraint_range's: + * MD code is allowed to setup constraint ranges for memory allocators, the + * primary use for this is to keep allocation for certain memory consumers + * such as mbuf pools withing address ranges that are reachable by devices + * that perform DMA. * - * UVM_IO_RANGES actually results into a call to uvm_pmr_use_inc() per range - * at uvm initialization. uvm_pmr_use_inc() can also be called after uvm_init() - * has completed. + * It is also to discourge memory allocations from being satisfied from ranges + * such as the ISA memory range, if they can be satisfied with allocation + * from other ranges. * - * Note: the upper bound is specified in the same way as to uvm_pglistalloc. - * Ex: a memory range of 16 bit is specified as: { 0, 0xffff }. - * Default: no special ranges in use. + * the MD ranges are defined in arch/ARCH/ARCH/machdep.c */ -#ifndef UVM_IO_RANGES -#define UVM_IO_RANGES \ - { \ - { 0, 0x00ffffffUL }, /* ISA memory */ \ - { 0, 0xffffffffUL }, /* 32-bit PCI memory */ \ - } -#endif - -/* UVM IO ranges are described in an array of struct uvm_io_ranges. */ -struct uvm_io_ranges { - paddr_t low; - paddr_t high; +struct uvm_constraint_range { + paddr_t ucr_low; + paddr_t ucr_high; }; +/* Constraint ranges, set by MD code. */ +extern struct uvm_constraint_range isa_constraint; +extern struct uvm_constraint_range dma_constraint; +extern struct uvm_constraint_range *uvm_md_constraints[]; + /* * uvm structure (vm global state: collected in one structure for ease * of reference...) @@ -103,7 +98,7 @@ struct uvm_io_ranges { struct uvm { /* vm_page related parameters */ - /* vm_page queues */ + /* vm_page queues */ struct pglist page_active; /* allocated pages, in use */ struct pglist page_inactive_swp;/* pages inactive (reclaim or free) */ struct pglist page_inactive_obj;/* pages inactive (reclaim or free) */ diff --git a/sys/uvm/uvm_extern.h b/sys/uvm/uvm_extern.h index 7941d55963f..e9ea11298e5 100644 --- a/sys/uvm/uvm_extern.h +++ b/sys/uvm/uvm_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_extern.h,v 1.86 2010/06/09 08:26:21 thib Exp $ */ +/* $OpenBSD: uvm_extern.h,v 1.87 2010/06/27 03:03:49 thib Exp $ */ /* $NetBSD: uvm_extern.h,v 1.57 2001/03/09 01:02:12 chs Exp $ */ /* @@ -205,6 +205,7 @@ typedef int vm_prot_t; #define UVM_KMF_NOWAIT 0x1 /* matches M_NOWAIT */ #define UVM_KMF_VALLOC 0x2 /* allocate VA only */ #define UVM_KMF_CANFAIL 0x4 /* caller handles failure */ +#define UVM_KMF_ZERO 0x08 /* zero pages */ #define UVM_KMF_TRYLOCK UVM_FLAG_TRYLOCK /* try locking only */ /* @@ -517,8 +518,11 @@ vaddr_t uvm_km_alloc1(vm_map_t, vsize_t, vsize_t, boolean_t); void uvm_km_free(vm_map_t, vaddr_t, vsize_t); void uvm_km_free_wakeup(vm_map_t, vaddr_t, vsize_t); -vaddr_t uvm_km_kmemalloc(vm_map_t, struct uvm_object *, - vsize_t, int); +vaddr_t uvm_km_kmemalloc_pla(struct vm_map *, + struct uvm_object *, vsize_t, int, paddr_t, + paddr_t, paddr_t, paddr_t, int); +#define uvm_km_kmemalloc(map, obj, sz, flags) \ + uvm_km_kmemalloc_pla(map, obj, sz, flags, 0, (paddr_t)-1, 0, 0, 0) struct vm_map *uvm_km_suballoc(vm_map_t, vaddr_t *, vaddr_t *, vsize_t, int, boolean_t, vm_map_t); @@ -528,7 +532,13 @@ vaddr_t uvm_km_valloc_wait(vm_map_t, vsize_t); vaddr_t uvm_km_valloc_align(struct vm_map *, vsize_t, vsize_t, int); vaddr_t uvm_km_valloc_prefer_wait(vm_map_t, vsize_t, voff_t); -void *uvm_km_getpage(boolean_t, int *); +void *uvm_km_getpage_pla(boolean_t, int *, paddr_t, paddr_t, + paddr_t, paddr_t); +/* Wrapper around old function prototype. */ +#define uvm_km_getpage(waitok, slowdown) \ + uvm_km_getpage_pla(((waitok) ? 0 : UVM_KMF_NOWAIT), (slowdown), \ + (paddr_t)0, (paddr_t)-1, 0, 0) + void uvm_km_putpage(void *); /* uvm_map.c */ diff --git a/sys/uvm/uvm_km.c b/sys/uvm/uvm_km.c index e00ee709591..19d22bb269e 100644 --- a/sys/uvm/uvm_km.c +++ b/sys/uvm/uvm_km.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_km.c,v 1.76 2010/02/12 01:35:14 tedu Exp $ */ +/* $OpenBSD: uvm_km.c,v 1.77 2010/06/27 03:03:49 thib Exp $ */ /* $NetBSD: uvm_km.c,v 1.42 2001/01/14 02:10:01 thorpej Exp $ */ /* @@ -326,7 +326,6 @@ uvm_km_pgremove_intrsafe(vaddr_t start, vaddr_t end) } } - /* * uvm_km_kmemalloc: lower level kernel memory allocator for malloc() * @@ -337,20 +336,29 @@ uvm_km_pgremove_intrsafe(vaddr_t start, vaddr_t end) * => we return KVA of memory allocated * => flags: NOWAIT, VALLOC - just allocate VA, TRYLOCK - fail if we can't * lock the map + * => low, high, alignment, boundary, nsegs are the corresponding parameters + * to uvm_pglistalloc + * => flags: ZERO - correspond to uvm_pglistalloc flags */ vaddr_t -uvm_km_kmemalloc(struct vm_map *map, struct uvm_object *obj, vsize_t size, - int flags) +uvm_km_kmemalloc_pla(struct vm_map *map, struct uvm_object *obj, vsize_t size, + int flags, paddr_t low, paddr_t high, paddr_t alignment, paddr_t boundary, + int nsegs) { vaddr_t kva, loopva; voff_t offset; struct vm_page *pg; + struct pglist pgl; + int pla_flags; UVMHIST_FUNC("uvm_km_kmemalloc"); UVMHIST_CALLED(maphist); UVMHIST_LOG(maphist," (map=%p, obj=%p, size=0x%lx, flags=%d)", map, obj, size, flags); KASSERT(vm_map_pmap(map) == pmap_kernel()); + /* UVM_KMF_VALLOC => !UVM_KMF_ZERO */ + KASSERT(!(flags & UVM_KMF_VALLOC) || + !(flags & UVM_KMF_ZERO)); /* * setup for call @@ -358,6 +366,8 @@ uvm_km_kmemalloc(struct vm_map *map, struct uvm_object *obj, vsize_t size, size = round_page(size); kva = vm_map_min(map); /* hint */ + if (nsegs == 0) + nsegs = atop(size); /* * allocate some virtual space @@ -394,28 +404,31 @@ uvm_km_kmemalloc(struct vm_map *map, struct uvm_object *obj, vsize_t size, * now allocate and map in the memory... note that we are the only ones * whom should ever get a handle on this area of VM. */ + TAILQ_INIT(&pgl); + pla_flags = 0; + if ((flags & UVM_KMF_NOWAIT) || + ((flags & UVM_KMF_CANFAIL) && + uvmexp.swpgonly - uvmexp.swpages <= atop(size))) + pla_flags |= UVM_PLA_NOWAIT; + else + pla_flags |= UVM_PLA_WAITOK; + if (flags & UVM_KMF_ZERO) + pla_flags |= UVM_PLA_ZERO; + if (uvm_pglistalloc(size, low, high, alignment, boundary, &pgl, nsegs, + pla_flags) != 0) { + /* Failed. */ + uvm_unmap(map, kva, kva + size); + return (0); + } loopva = kva; while (loopva != kva + size) { - pg = uvm_pagealloc(obj, offset, NULL, 0); - if (pg) { - atomic_clearbits_int(&pg->pg_flags, PG_BUSY); - UVM_PAGE_OWN(pg, NULL); - } - - if (__predict_false(pg == NULL)) { - if ((flags & UVM_KMF_NOWAIT) || - ((flags & UVM_KMF_CANFAIL) && - uvmexp.swpgonly == uvmexp.swpages)) { - /* free everything! */ - uvm_unmap(map, kva, kva + size); - return (0); - } else { - uvm_wait("km_getwait2"); /* sleep here */ - continue; - } - } - + pg = TAILQ_FIRST(&pgl); + TAILQ_REMOVE(&pgl, pg, pageq); + uvm_pagealloc_pg(pg, obj, offset, NULL); + atomic_clearbits_int(&pg->pg_flags, PG_BUSY); + UVM_PAGE_OWN(pg, NULL); + /* * map it in: note that we call pmap_enter with the map and * object unlocked in case we are kmem_map. @@ -432,6 +445,7 @@ uvm_km_kmemalloc(struct vm_map *map, struct uvm_object *obj, vsize_t size, loopva += PAGE_SIZE; offset += PAGE_SIZE; } + KASSERT(TAILQ_EMPTY(&pgl)); pmap_update(pmap_kernel()); UVMHIST_LOG(maphist,"<- done (kva=0x%lx)", kva,0,0,0); @@ -666,7 +680,7 @@ int uvm_km_pages_free; /* number of pages currently on free list */ * uvm_km_page allocator, __HAVE_PMAP_DIRECT arch * On architectures with machine memory direct mapped into a portion * of KVM, we have very little work to do. Just get a physical page, - * and find and return its VA. We use the poolpage functions for this. + * and find and return its VA. */ void uvm_km_page_init(void) @@ -674,34 +688,6 @@ uvm_km_page_init(void) /* nothing */ } -void * -uvm_km_getpage(boolean_t waitok, int *slowdown) -{ - struct vm_page *pg; - vaddr_t va; - - *slowdown = 0; - again: - pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE); - if (__predict_false(pg == NULL)) { - if (waitok) { - uvm_wait("plpg"); - goto again; - } else - return (NULL); - } - va = pmap_map_direct(pg); - if (__predict_false(va == 0)) - uvm_pagefree(pg); - return ((void *)va); -} - -void -uvm_km_putpage(void *v) -{ - uvm_pagefree(pmap_unmap_direct((vaddr_t)v)); -} - #else /* * uvm_km_page allocator, non __HAVE_PMAP_DIRECT archs @@ -714,13 +700,24 @@ uvm_km_putpage(void *v) * not zero filled. */ -struct mutex uvm_km_mtx; -int uvm_km_pages_lowat; /* allocate more when reserve drops below this */ -struct km_page { - struct km_page *next; -} *uvm_km_pages_head; +#define UVM_KM_PAGES_LOWAT_MAX (2048) +#define UVM_KM_PAGES_HIWAT_MAX (4 * UVM_KM_PAGES_LOWAT_MAX) + +struct uvm_km_pages { + struct mutex mtx; + + /* Low and high water mark for addresses. */ + int lowat; + int hiwat; -struct proc *uvm_km_proc; + /* Kernel address pool. */ + int free; + vaddr_t page[UVM_KM_PAGES_HIWAT_MAX]; + + struct proc *km_proc; +}; + +struct uvm_km_pages uvm_km_pages; void uvm_km_createthread(void *); void uvm_km_thread(void *); @@ -734,31 +731,36 @@ void uvm_km_thread(void *); void uvm_km_page_init(void) { - struct km_page *page; int lowat_min; int i; - mtx_init(&uvm_km_mtx, IPL_VM); - if (!uvm_km_pages_lowat) { + mtx_init(&uvm_km_pages.mtx, IPL_VM); + if (!uvm_km_pages.lowat) { /* based on physmem, calculate a good value here */ - uvm_km_pages_lowat = physmem / 256; - if (uvm_km_pages_lowat > 2048) - uvm_km_pages_lowat = 2048; + uvm_km_pages.lowat = physmem / 256; lowat_min = physmem < atop(16 * 1024 * 1024) ? 32 : 128; - if (uvm_km_pages_lowat < lowat_min) - uvm_km_pages_lowat = lowat_min; + if (uvm_km_pages.lowat < lowat_min) + uvm_km_pages.lowat = lowat_min; } - - for (i = 0; i < uvm_km_pages_lowat * 4; i++) { - page = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE); - page->next = uvm_km_pages_head; - uvm_km_pages_head = page; + if (uvm_km_pages.lowat > UVM_KM_PAGES_LOWAT_MAX) + uvm_km_pages.lowat = UVM_KM_PAGES_LOWAT_MAX; + uvm_km_pages.hiwat = 4 * uvm_km_pages.lowat; + if (uvm_km_pages.hiwat > UVM_KM_PAGES_HIWAT_MAX) + uvm_km_pages.hiwat = UVM_KM_PAGES_HIWAT_MAX; + + for (i = 0; i < uvm_km_pages.hiwat; i++) { + uvm_km_pages.page[i] = (vaddr_t)uvm_km_kmemalloc(kernel_map, + NULL, PAGE_SIZE, UVM_KMF_NOWAIT|UVM_KMF_VALLOC); + if (uvm_km_pages.page[i] == NULL) + break; } - uvm_km_pages_free = i; + uvm_km_pages.free = i; + for ( ; i < UVM_KM_PAGES_HIWAT_MAX; i++) + uvm_km_pages.page[i] = NULL; /* tone down if really high */ - if (uvm_km_pages_lowat > 512) - uvm_km_pages_lowat = 512; + if (uvm_km_pages.lowat > 512) + uvm_km_pages.lowat = 512; kthread_create_deferred(uvm_km_createthread, NULL); } @@ -766,7 +768,7 @@ uvm_km_page_init(void) void uvm_km_createthread(void *arg) { - kthread_create(uvm_km_thread, NULL, &uvm_km_proc, "kmthread"); + kthread_create(uvm_km_thread, NULL, &uvm_km_pages.km_proc, "kmthread"); } /* @@ -778,74 +780,123 @@ uvm_km_createthread(void *arg) void uvm_km_thread(void *arg) { - struct km_page *head, *tail, *page; - int i, want; - - for (i = want = 16; ; ) { - if (i < want || uvm_km_pages_free >= uvm_km_pages_lowat) - tsleep(&uvm_km_pages_head, PVM, "kmalloc", 0); - for (i = 0; i < want; i++) { - page = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE); - if (i == 0) - head = tail = page; - if (page == NULL) - break; - page->next = head; - head = page; + vaddr_t pg[16]; + int i; + + for (;;) { + mtx_enter(&uvm_km_pages.mtx); + if (uvm_km_pages.free >= uvm_km_pages.lowat) { + msleep(&uvm_km_pages.km_proc, &uvm_km_pages.mtx, + PVM, "kmalloc", 0); + } + + for (i = 0; i < nitems(pg); i++) { + pg[i] = (vaddr_t)uvm_km_kmemalloc(kernel_map, NULL, + PAGE_SIZE, UVM_KMF_VALLOC); } - if (head != NULL) { - mtx_enter(&uvm_km_mtx); - tail->next = uvm_km_pages_head; - uvm_km_pages_head = head; - uvm_km_pages_free += i; - mtx_leave(&uvm_km_mtx); + + mtx_enter(&uvm_km_pages.mtx); + for (i = 0; i < nitems(pg); i++) { + if (uvm_km_pages.free == nitems(uvm_km_pages.page)) + break; + else + uvm_km_pages.page[uvm_km_pages.free++] = pg[i]; } - if (uvm_km_pages_free) - wakeup(&uvm_km_pages_free); + + wakeup(&uvm_km_pages.free); + mtx_leave(&uvm_km_pages.mtx); + + /* Cleanup left-over pages (if any). */ + for (; i < nitems(pg); i++) + uvm_km_free_wakeup(kernel_map, pg[i], PAGE_SIZE); } } +#endif - -/* - * Allocate one page. We can sleep for more if the caller - * permits it. Wake up the thread if we've dropped below lowat. - */ void * -uvm_km_getpage(boolean_t waitok, int *slowdown) +uvm_km_getpage_pla(int flags, int *slowdown, paddr_t low, paddr_t high, + paddr_t alignment, paddr_t boundary) { - struct km_page *page = NULL; + struct pglist pgl; + int pla_flags; + struct vm_page *pg; + vaddr_t va; *slowdown = 0; - mtx_enter(&uvm_km_mtx); - for (;;) { - page = uvm_km_pages_head; - if (page) { - uvm_km_pages_head = page->next; - uvm_km_pages_free--; - break; + pla_flags = (flags & UVM_KMF_NOWAIT) ? UVM_PLA_NOWAIT : UVM_PLA_WAITOK; + if (flags & UVM_KMF_ZERO) + pla_flags |= UVM_PLA_ZERO; + TAILQ_INIT(&pgl); + if (uvm_pglistalloc(PAGE_SIZE, low, high, alignment, boundary, &pgl, + 1, pla_flags) != 0) + return NULL; + pg = TAILQ_FIRST(&pgl); + KASSERT(pg != NULL && TAILQ_NEXT(pg, pageq) == NULL); + TAILQ_REMOVE(&pgl, pg, pageq); + +#ifdef __HAVE_PMAP_DIRECT + va = pmap_map_direct(pg); + if (__predict_false(va == 0)) + uvm_pagefree(pg); + +#else /* !__HAVE_PMAP_DIRECT */ + mtx_enter(&uvm_km_pages.mtx); + while (uvm_km_pages.free == 0) { + if (flags & UVM_KMF_NOWAIT) { + mtx_leave(&uvm_km_pages.mtx); + uvm_pagefree(pg); + return NULL; } - if (!waitok) - break; - msleep(&uvm_km_pages_free, &uvm_km_mtx, PVM, "getpage", 0); + msleep(&uvm_km_pages.free, &uvm_km_pages.mtx, PVM, "getpage", + 0); } - mtx_leave(&uvm_km_mtx); - if (uvm_km_pages_free < uvm_km_pages_lowat) { - if (curproc != uvm_km_proc) - *slowdown = 1; - wakeup(&uvm_km_pages_head); + + va = uvm_km_pages.page[--uvm_km_pages.free]; + if (uvm_km_pages.free < uvm_km_pages.lowat && + curproc != uvm_km_pages.km_proc) { + *slowdown = 1; + wakeup(&uvm_km_pages.km_proc); } - return (page); + mtx_leave(&uvm_km_pages.mtx); + + + atomic_setbits_int(&pg->pg_flags, PG_FAKE); + UVM_PAGE_OWN(pg, NULL); + + pmap_enter(kernel_map->pmap, va, VM_PAGE_TO_PHYS(pg), UVM_PROT_RW, + PMAP_WIRED | VM_PROT_READ | VM_PROT_WRITE); + pmap_update(kernel_map->pmap); + +#endif /* !__HAVE_PMAP_DIRECT */ + return ((void *)va); } void uvm_km_putpage(void *v) { - struct km_page *page = v; + vaddr_t va = (vaddr_t)v; + struct vm_page *pg; + +#ifdef __HAVE_PMAP_DIRECT + pg = pmap_unmap_direct(va); +#else /* !__HAVE_PMAP_DIRECT */ + paddr_t pa; + if (!pmap_extract(pmap_kernel(), va, &pa)) + panic("lost pa"); + pg = PHYS_TO_VM_PAGE(pa); + + KASSERT(pg != NULL); - mtx_enter(&uvm_km_mtx); - page->next = uvm_km_pages_head; - uvm_km_pages_head = page; - uvm_km_pages_free++; - mtx_leave(&uvm_km_mtx); + pmap_remove(kernel_map->pmap, va, va + PAGE_SIZE); + pmap_update(kernel_map->pmap); + + mtx_enter(&uvm_km_pages.mtx); + if (uvm_km_pages.free < uvm_km_pages.hiwat) + uvm_km_pages.page[uvm_km_pages.free++] = va; + else + uvm_km_free_wakeup(kernel_map, va, PAGE_SIZE); + mtx_leave(&uvm_km_pages.mtx); +#endif /* !__HAVE_PMAP_DIRECT */ + + uvm_pagefree(pg); } -#endif diff --git a/sys/uvm/uvm_page.c b/sys/uvm/uvm_page.c index d40e6a41abb..6a038d8d015 100644 --- a/sys/uvm/uvm_page.c +++ b/sys/uvm/uvm_page.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_page.c,v 1.100 2010/04/22 19:02:55 oga Exp $ */ +/* $OpenBSD: uvm_page.c,v 1.101 2010/06/27 03:03:49 thib Exp $ */ /* $NetBSD: uvm_page.c,v 1.44 2000/11/27 08:40:04 chs Exp $ */ /* @@ -777,6 +777,33 @@ uvm_shutdown(void) } /* + * Perform insert of a given page in the specified anon of obj. + * This is basically, uvm_pagealloc, but with the page already given. + */ +void +uvm_pagealloc_pg(struct vm_page *pg, struct uvm_object *obj, voff_t off, + struct vm_anon *anon) +{ + int flags; + + flags = PG_BUSY | PG_FAKE; + pg->offset = off; + pg->uobject = obj; + pg->uanon = anon; + + if (anon) { + anon->an_page = pg; + flags |= PQ_ANON; + } else if (obj) + uvm_pageinsert(pg); + atomic_setbits_int(&pg->pg_flags, flags); +#if defined(UVM_PAGE_TRKOWN) + pg->owner_tag = NULL; +#endif + UVM_PAGE_OWN(pg, "new alloc"); +} + +/* * uvm_pagealloc_strat: allocate vm_page from a particular free list. * * => return null if no pages free @@ -836,23 +863,11 @@ uvm_pagealloc(struct uvm_object *obj, voff_t off, struct vm_anon *anon, pg = TAILQ_FIRST(&pgl); KASSERT(pg != NULL && TAILQ_NEXT(pg, pageq) == NULL); - pg->offset = off; - pg->uobject = obj; - pg->uanon = anon; + uvm_pagealloc_pg(pg, obj, off, anon); KASSERT((pg->pg_flags & PG_DEV) == 0); atomic_setbits_int(&pg->pg_flags, PG_BUSY|PG_CLEAN|PG_FAKE); if (flags & UVM_PGA_ZERO) atomic_clearbits_int(&pg->pg_flags, PG_CLEAN); - if (anon) { - anon->an_page = pg; - atomic_setbits_int(&pg->pg_flags, PQ_ANON); - } else if (obj) - uvm_pageinsert(pg); - -#if defined(UVM_PAGE_TRKOWN) - pg->owner_tag = NULL; -#endif - UVM_PAGE_OWN(pg, "new alloc"); UVMHIST_LOG(pghist, "allocated pg %p/%lx", pg, (u_long)VM_PAGE_TO_PHYS(pg), 0, 0); diff --git a/sys/uvm/uvm_page.h b/sys/uvm/uvm_page.h index eda9030fe63..c8e2b04fd36 100644 --- a/sys/uvm/uvm_page.h +++ b/sys/uvm/uvm_page.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_page.h,v 1.42 2010/04/22 19:02:55 oga Exp $ */ +/* $OpenBSD: uvm_page.h,v 1.43 2010/06/27 03:03:49 thib Exp $ */ /* $NetBSD: uvm_page.h,v 1.19 2000/12/28 08:24:55 chs Exp $ */ /* @@ -249,6 +249,8 @@ void uvm_pagewait(struct vm_page *, int); void uvm_pagewake(struct vm_page *); void uvm_pagewire(struct vm_page *); void uvm_pagezero(struct vm_page *); +void uvm_pagealloc_pg(struct vm_page *, struct uvm_object *, + voff_t, struct vm_anon *); int uvm_page_lookup_freelist(struct vm_page *); diff --git a/sys/uvm/uvm_pglist.c b/sys/uvm/uvm_pglist.c index 94b68efba13..17fd8751bec 100644 --- a/sys/uvm/uvm_pglist.c +++ b/sys/uvm/uvm_pglist.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_pglist.c,v 1.37 2010/06/10 08:48:36 thib Exp $ */ +/* $OpenBSD: uvm_pglist.c,v 1.38 2010/06/27 03:03:49 thib Exp $ */ /* $NetBSD: uvm_pglist.c,v 1.13 2001/02/18 21:19:08 chs Exp $ */ /*- @@ -77,7 +77,6 @@ u_long uvm_pglistalloc_npages; * UVM_PLA_NOWAIT fail if allocation fails * UVM_PLA_WAITOK wait for memory to become avail * UVM_PLA_ZERO return zeroed memory - * UVM_PLA_TRYCONTIG caller (device) prefers p-linear memory */ int diff --git a/sys/uvm/uvm_pmemrange.c b/sys/uvm/uvm_pmemrange.c index 54d3f6960d6..d4c6bd87789 100644 --- a/sys/uvm/uvm_pmemrange.c +++ b/sys/uvm/uvm_pmemrange.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_pmemrange.c,v 1.14 2010/06/23 09:36:03 thib Exp $ */ +/* $OpenBSD: uvm_pmemrange.c,v 1.15 2010/06/27 03:03:49 thib Exp $ */ /* * Copyright (c) 2009, 2010 Ariane van der Steldt <ariane@stack.nl> @@ -109,7 +109,6 @@ void uvm_pmr_assertvalid(struct uvm_pmemrange *pmr); #define uvm_pmr_assertvalid(pmr) do {} while (0) #endif - int uvm_pmr_get1page(psize_t, int, struct pglist *, paddr_t, paddr_t); @@ -1305,7 +1304,26 @@ uvm_pmr_split(paddr_t pageno) KASSERT(pmr->low < pageno); KASSERT(pmr->high > pageno); + /* + * uvm_pmr_allocpmr() calls into malloc() which in turn calls into + * uvm_kmemalloc which calls into pmemrange, making the locking + * a bit hard, so we just race! + */ + uvm_unlock_fpageq(); drain = uvm_pmr_allocpmr(); + uvm_lock_fpageq(); + pmr = uvm_pmemrange_find(pageno); + if (pmr == NULL || !(pmr->low < pageno)) { + /* + * We lost the race since someone else ran this or a related + * function, however this should be triggered very rarely so + * we just leak the pmr. + */ + printf("uvm_pmr_split: lost one pmr\n"); + uvm_unlock_fpageq(); + return; + } + drain->low = pageno; drain->high = pmr->high; drain->use = pmr->use; @@ -1379,37 +1397,29 @@ void uvm_pmr_use_inc(paddr_t low, paddr_t high) { struct uvm_pmemrange *pmr; + paddr_t sz; - /* - * If high+1 == 0 and low == 0, then you are increasing use - * of the whole address space, which won't make any difference. - * Skip in that case. - */ + /* pmr uses page numbers, translate low and high. */ high++; - if (high == 0 && low == 0) - return; - - /* - * pmr uses page numbers, translate low and high. - */ - low = atop(round_page(low)); high = atop(trunc_page(high)); + low = atop(round_page(low)); uvm_pmr_split(low); uvm_pmr_split(high); uvm_lock_fpageq(); - /* Increase use count on segments in range. */ RB_FOREACH(pmr, uvm_pmemrange_addr, &uvm.pmr_control.addr) { if (PMR_IS_SUBRANGE_OF(pmr->low, pmr->high, low, high)) { TAILQ_REMOVE(&uvm.pmr_control.use, pmr, pmr_use); pmr->use++; + sz += pmr->high - pmr->low; uvm_pmemrange_use_insert(&uvm.pmr_control.use, pmr); } uvm_pmr_assertvalid(pmr); } - uvm_unlock_fpageq(); + + KASSERT(sz >= high - low); } /* @@ -1420,19 +1430,21 @@ uvm_pmr_use_inc(paddr_t low, paddr_t high) * (And if called in between, you're dead.) */ struct uvm_pmemrange * -uvm_pmr_allocpmr() +uvm_pmr_allocpmr(void) { struct uvm_pmemrange *nw; int i; + /* We're only ever hitting the !uvm.page_init_done case for now. */ if (!uvm.page_init_done) { nw = (struct uvm_pmemrange *) uvm_pageboot_alloc(sizeof(struct uvm_pmemrange)); - bzero(nw, sizeof(struct uvm_pmemrange)); } else { nw = malloc(sizeof(struct uvm_pmemrange), - M_VMMAP, M_NOWAIT | M_ZERO); + M_VMMAP, M_NOWAIT); } + KASSERT(nw != NULL); + bzero(nw, sizeof(struct uvm_pmemrange)); RB_INIT(&nw->addr); for (i = 0; i < UVM_PMR_MEMTYPE_MAX; i++) { RB_INIT(&nw->size[i]); @@ -1441,8 +1453,6 @@ uvm_pmr_allocpmr() return nw; } -static const struct uvm_io_ranges uvm_io_ranges[] = UVM_IO_RANGES; - /* * Initialization of pmr. * Called by uvm_page_init. @@ -1458,15 +1468,18 @@ uvm_pmr_init(void) TAILQ_INIT(&uvm.pmr_control.use); RB_INIT(&uvm.pmr_control.addr); + /* By default, one range for the entire address space. */ new_pmr = uvm_pmr_allocpmr(); new_pmr->low = 0; - new_pmr->high = atop((paddr_t)-1) + 1; + new_pmr->high = atop((paddr_t)-1) + 1; RB_INSERT(uvm_pmemrange_addr, &uvm.pmr_control.addr, new_pmr); uvm_pmemrange_use_insert(&uvm.pmr_control.use, new_pmr); - for (i = 0; i < nitems(uvm_io_ranges); i++) - uvm_pmr_use_inc(uvm_io_ranges[i].low, uvm_io_ranges[i].high); + for (i = 0; uvm_md_constraints[i] != NULL; i++) { + uvm_pmr_use_inc(uvm_md_constraints[i]->ucr_low, + uvm_md_constraints[i]->ucr_high); + } } /* |