[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-misc
Subject:    Re: uvm_mapent_alloc: out of static map entries on 4.3 i386
From:       mickey <mickey () lucifier ! net>
Date:       2008-05-19 13:06:39
Message-ID: 20080519130639.GA27634 () lucifier ! net
[Download RAW message or body]

On Fri, May 16, 2008 at 08:21:25AM -0700, Darrian Hale wrote:
> Can you please point me to where the diffs you refer to reside?
> 
> I'd definitely like to try them out.

most of these are filed in sendbug (some for months) already...
here is a cumulative diff also w/ a bonus himem high-quality
software (in caase you managed to squeeze more than 4g of memory
in your box ;).
cu
-- 
    paranoic mickey       (my employers have changed but, the name has remained)

Index: arch/i386/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/i386/conf/GENERIC,v
retrieving revision 1.603
diff -u -r1.603 GENERIC
--- arch/i386/conf/GENERIC	25 Feb 2008 23:16:47 -0000	1.603
+++ arch/i386/conf/GENERIC	7 May 2008 12:55:43 -0000
@@ -37,6 +37,8 @@
 config		bsd	swap generic
 
 mainbus0 at root
+himem0	at root		# himem.sys
+scsibus* at himem?
 
 cpu0	at mainbus?
 bios0	at mainbus0
Index: arch/i386/conf/files.i386
===================================================================
RCS file: /cvs/src/sys/arch/i386/conf/files.i386,v
retrieving revision 1.172
diff -u -r1.172 files.i386
--- arch/i386/conf/files.i386	4 Mar 2008 21:14:29 -0000	1.172
+++ arch/i386/conf/files.i386	7 May 2008 12:55:43 -0000
@@ -440,6 +440,10 @@
 attach	esm at mainbus
 file	arch/i386/i386/esm.c			esm needs-flag
 
+device	himem: scsi
+attach	himem at root
+file    arch/i386/i386/himem.c			himem needs-flag
+
 #
 # VESA
 #
Index: arch/i386/i386/autoconf.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/autoconf.c,v
retrieving revision 1.78
diff -u -r1.78 autoconf.c
--- arch/i386/i386/autoconf.c	27 Dec 2007 18:04:27 -0000	1.78
+++ arch/i386/i386/autoconf.c	7 May 2008 12:55:43 -0000
@@ -71,6 +71,7 @@
 #include <dev/cons.h>
 
 #include "ioapic.h"
+#include "himem.h"
 
 #if NIOAPIC > 0
 #include <machine/i82093var.h>
@@ -117,6 +118,10 @@
 
 	if (config_rootfound("mainbus", NULL) == NULL)
 		panic("cpu_configure: mainbus not configured");
+
+#if NHIMEM > 0
+	config_rootfound("himem", NULL);
+#endif
 
 #if NIOAPIC > 0
 	if (nioapics > 0)
Index: arch/i386/i386/himem.c
===================================================================
RCS file: arch/i386/i386/himem.c
diff -N arch/i386/i386/himem.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/i386/i386/himem.c	9 May 2008 09:23:37 -0000
@@ -0,0 +1,476 @@
+/*	$OpenBSD$	*/
+
+/*
+ * Copyright (c) 2008 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/kthread.h>
+#include <sys/queue.h>
+#include <sys/mutex.h>
+#include <sys/buf.h>
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_disk.h>
+#include <scsi/scsiconf.h>
+#include <scsi/sdvar.h>
+
+#include <uvm/uvm.h>
+
+/* arbitrary numbers */
+#define	HIMEM_MAXCMDS	256	/* each one is a page */
+
+/* derived from page table structure */
+#define	HIMEM_OFFSET	((sizeof(struct hibuf) + 7) / 8)
+#define	HIMEM_MAXSEGS	(512 - HIMEM_OFFSET - 2)
+#define	HIMEM_MAXPHYS	(HIMEM_MAXSEGS * PAGE_SIZE)
+
+#define	HIMEM_PDE	(8)
+#define	HIMEM_VA	(HIMEM_PDE << 21)
+#define	HIMEM_LOW	(HIMEM_VA + (PAGE_SIZE * HIMEM_OFFSET))
+#define	HIMEM_HIGH	(HIMEM_VA + (PAGE_SIZE * 512))
+#define	PDE_MASK	((512 * (PAGE_SIZE / DEV_BSIZE)) - 1)
+
+void himem_zefix(u_int64_t *, void *, void *, u_int);	/* locore.s */
+
+struct hibuf {
+	TAILQ_ENTRY(hibuf) hb_list;
+	paddr_t hb_pa;
+	struct scsi_xfer *hb_xs;
+	void *hb_src, *hb_dst;
+	u_int hb_bno, hb_len;
+	int hb_flags;
+#define	HIMEM_WAKE	0x0001
+};
+
+struct himem_softc {
+	struct device sc_dev;
+	struct scsi_link sc_link;
+
+	int sc_flags;
+#define	HIMEM_RDONLY	0x0001
+#define	HIMEM_DISKLABEL	0x0002
+	int sc_size;	/* blocks */
+
+	struct proc *sc_kthread;
+	u_int64_t *sc_pdir;
+	paddr_t sc_paddr;
+	struct mutex sc_inmtx;
+	struct mutex sc_freemtx;
+	TAILQ_HEAD(hibuf_head, hibuf) sc_free, sc_in;
+};
+
+int  himem_scsi_cmd(struct scsi_xfer *);
+int  himem_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int, struct proc *);
+void himeminphys(struct buf *bp);
+
+struct scsi_adapter himem_switch = {
+	himem_scsi_cmd, himeminphys, 0, 0, himem_scsi_ioctl
+};
+
+struct scsi_device himem_dev = {
+	NULL, NULL, NULL, NULL
+};
+
+int  himem_match(struct device *, void *, void *);
+void himem_attach(struct device *, struct device *, void *);
+
+struct cfattach himem_ca = {
+	sizeof(struct himem_softc), himem_match, himem_attach
+};
+
+struct cfdriver himem_cd = {
+	NULL, "himem", DV_DULL
+};
+
+void himem(void *);
+void himem_create(void *);
+
+int
+himem_match(struct device *parent, void *match, void *aux)
+{
+	extern u_int64_t avail_end, avail_end2;
+	struct cfdata *cf = match;
+
+	if (cf->cf_unit)
+		return 0;
+
+	/* if no PAE or too little memory then screw it */
+	if (!(cpu_feature & CPUID_PAE) || avail_end2 == 0 ||
+	    (avail_end2 - avail_end) < 4 * HIMEM_MAXCMDS * PAGE_SIZE)
+		return 0;
+
+	return 1;
+}
+
+void
+himem_attach(struct device *parent, struct device *self, void *aux)
+{
+	extern u_int64_t avail_end2;
+	struct himem_softc *sc = (struct himem_softc *)self;
+	struct disklabel *lp;
+	struct hibuf *bp;
+	paddr_t pa;
+	vaddr_t va;
+	int i, pdsize;
+	
+	TAILQ_INIT(&sc->sc_in);
+	TAILQ_INIT(&sc->sc_free);
+	mtx_init(&sc->sc_inmtx, IPL_SCHED);
+	mtx_init(&sc->sc_freemtx, IPL_BIO);
+
+	pdsize = 4 * PAGE_SIZE;
+	sc->sc_pdir = (u_int64_t *)uvm_km_alloc1(kernel_map, pdsize,
+	    PAGE_SIZE, 1);
+	if (!sc->sc_pdir) {
+		printf(": cannot allocate page index\n");
+		return;
+	}
+
+#define	vatopa(va) pmap_extract(pmap_kernel(), (vaddr_t)va, &pa)
+	/* we do know like for sure there ain't no like user space */
+	vatopa((vaddr_t)sc->sc_pdir + 0 * PAGE_SIZE);	sc->sc_paddr = pa;
+	sc->sc_pdir[0] = pa | PG_V;
+	vatopa((vaddr_t)sc->sc_pdir + 1 * PAGE_SIZE);
+	sc->sc_pdir[1] = pa | PG_V;
+	vatopa((vaddr_t)sc->sc_pdir + 2 * PAGE_SIZE);
+	sc->sc_pdir[2] = pa | PG_V;
+	vatopa((vaddr_t)sc->sc_pdir + 3 * PAGE_SIZE);
+	sc->sc_pdir[3] = pa | PG_V;
+
+	/* 8M of kernel code is ment to be enough for everbody */
+	sc->sc_pdir[(KERNBASE >> 21) + 0] = 0x000000 |
+	    PG_KW | PG_M | PG_U | PG_V | PG_PS;
+	sc->sc_pdir[(KERNBASE >> 21) + 1] = 0x200000 |
+	    PG_KW | PG_M | PG_U | PG_V | PG_PS;
+	sc->sc_pdir[(KERNBASE >> 21) + 2] = 0x400000 |
+	    PG_KW | PG_M | PG_U | PG_V | PG_PS;
+	sc->sc_pdir[(KERNBASE >> 21) + 3] = 0x600000 |
+	    PG_KW | PG_M | PG_U | PG_V | PG_PS;
+
+	bp = (struct hibuf *)uvm_km_alloc1(kernel_map,
+	    HIMEM_MAXCMDS * PAGE_SIZE, PAGE_SIZE, 1);
+	if (!bp) {
+		uvm_km_free(kmem_map, (vaddr_t)sc->sc_pdir, pdsize);
+		printf(": no memory for buffers\n");
+		return;
+	}
+
+	/* each buf is a page table and hibuf in one! */
+	for (i = HIMEM_MAXCMDS, va = (vaddr_t)bp; i--; va += PAGE_SIZE) {
+		bp = (struct hibuf *)va;
+		TAILQ_INSERT_TAIL(&sc->sc_free, bp, hb_list);
+		pmap_extract(pmap_kernel(), va, &bp->hb_pa);
+	}
+
+	sc->sc_size = (avail_end2 - 0x100000000ULL) / DEV_BSIZE;
+	printf(": size %uMB\n", sc->sc_size / 2048);
+
+	/* set a fake diskalbel */
+	lp = (void *)uvm_km_zalloc(kernel_map, round_page(sizeof(*lp)));
+	if (lp) {
+		lp->d_secsize = DEV_BSIZE;
+		lp->d_ntracks = 255;
+		lp->d_nsectors = 63;
+		lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+		lp->d_ncylinders = sc->sc_size / lp->d_secpercyl;
+		lp->d_type = DTYPE_SCSI;
+		strncpy(lp->d_typename, "SCSI disk", sizeof(lp->d_typename));
+		strncpy(lp->d_packname, "HIMEM drive", sizeof(lp->d_packname));
+		DL_SETDSIZE(lp, sc->sc_size);
+		lp->d_rpm = 32768;
+		lp->d_interleave = 1;
+		lp->d_version = 1;
+		lp->d_flags = 0;
+		lp->d_bbsize = 8192;
+		lp->d_sbsize = 65536;
+		lp->d_magic = DISKMAGIC;
+		lp->d_magic2 = DISKMAGIC;
+
+		lp->d_npartitions = MAXPARTITIONS;
+		lp->d_partitions[0].p_fstype = FS_BSDFFS;
+		DL_SETPSIZE(&lp->d_partitions[0], sc->sc_size);
+		DL_SETPOFFSET(&lp->d_partitions[0], 0);
+		lp->d_partitions[0].p_fragblock =
+		    DISKLABELV1_FFS_FRAGBLOCK(4096, 4);
+		DL_SETPSIZE(&lp->d_partitions[RAW_PART], sc->sc_size);
+		DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
+
+		lp->d_checksum = dkcksum(lp);
+
+		/* write out the label */
+		vatopa(lp);
+		sc->sc_pdir[HIMEM_PDE] = PG_KW | PG_U | PG_M | PG_V | PG_PS |
+		    (pa & ~(0x200000 - 1));
+		sc->sc_pdir[HIMEM_PDE+1] = PG_KW | PG_U | PG_M | PG_V | PG_PS |
+		    0x100000000ULL;
+
+		himem_zefix(sc->sc_pdir,
+		    (char *)HIMEM_VA + (pa & (0x200000 - 1)),
+		    (char *)HIMEM_HIGH + LABELSECTOR * DEV_BSIZE, DEV_BSIZE);
+
+		sc->sc_pdir[HIMEM_PDE] = 0;
+		sc->sc_pdir[HIMEM_PDE+1] = 0;
+		uvm_km_free(kernel_map, (vaddr_t)lp, round_page(sizeof(*lp)));
+	}
+#undef vatopa
+
+	kthread_create_deferred(himem_create, sc);
+}
+
+void
+himem_create(void *v)
+{
+	struct himem_softc *sc = v;
+
+	kthread_create(himem, sc, &sc->sc_kthread, "himem.sys");
+}
+
+int
+himem_scsi_cmd(struct scsi_xfer *xs)
+{
+	struct scsi_link *link = xs->sc_link;
+	struct himem_softc *sc = link->adapter_softc;
+	struct scsi_read_cap_data rcd;
+	struct scsi_inquiry_data inq;
+	struct hibuf *bp;
+	u_int64_t *ptes;
+	paddr_t pa;
+	vaddr_t va, eva;
+	u_int bno, bcnt;
+	int s, res;
+
+	s = splbio();
+	if (link->target > 0 || !sc->sc_size || link->lun != 0) {
+		bzero(&xs->sense, sizeof(xs->sense));
+		xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
+		xs->sense.flags = SKEY_ILLEGAL_REQUEST;
+		xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */
+		xs->error = XS_SENSE;
+		scsi_done(xs);
+		splx(s);
+		return (COMPLETE);
+	}
+
+	xs->error = XS_NOERROR;
+	switch (xs->cmd->opcode) {
+	default:
+		xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
+		xs->sense.flags = SKEY_ILLEGAL_REQUEST;
+		xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */
+		xs->error = XS_SENSE;
+		scsi_done(xs);
+		splx(s);
+		return (COMPLETE);
+
+	case TEST_UNIT_READY:
+	case START_STOP:
+	case PREVENT_ALLOW:
+		splx(s);
+		return COMPLETE;
+
+	case INQUIRY:
+		bzero(&inq, sizeof(inq));
+		inq.device = T_DIRECT;
+		inq.dev_qual2 = 0;
+		inq.version = 2;
+		inq.response_format = 2;
+		inq.additional_length = 32;
+		strlcpy(inq.vendor, "McIkye ", sizeof(inq.vendor));
+		strlcpy(inq.product, "HIMEM drive    ", sizeof(inq.product));
+		strlcpy(inq.revision, "1.1", sizeof(inq.revision));
+		bcopy(&inq, xs->data, MIN(sizeof(inq), xs->datalen));
+		scsi_done(xs);
+		splx(s);
+		return COMPLETE;
+
+	case READ_CAPACITY:
+		bzero(&rcd, sizeof(rcd));
+		_lto4b(sc->sc_size - 1, rcd.addr);
+		_lto4b(DEV_BSIZE, rcd.length);
+		bcopy(&rcd, xs->data, MIN(sizeof(rcd), xs->datalen));
+		scsi_done(xs);
+		splx(s);
+		return COMPLETE;
+
+	case SYNCHRONIZE_CACHE:
+		mtx_enter(&sc->sc_inmtx);
+		if (!TAILQ_EMPTY(&sc->sc_in)) {
+			bp = TAILQ_LAST(&sc->sc_in, hibuf_head);
+			bp->hb_flags |= HIMEM_WAKE;
+			msleep(bp, &sc->sc_inmtx, PRIBIO, "himem.sync", 0);
+		}
+		mtx_leave(&sc->sc_inmtx);
+		scsi_done(xs);
+		splx(s);
+		return COMPLETE;
+
+	case WRITE_COMMAND:
+	case WRITE_BIG:
+		if (sc->sc_flags & HIMEM_RDONLY) {
+			xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
+			xs->sense.flags = SKEY_WRITE_PROTECT;
+			xs->sense.add_sense_code = 0;
+			xs->error = XS_SENSE;
+			scsi_done(xs);
+			splx(s);
+			return COMPLETE;
+		}
+	case READ_COMMAND:
+	case READ_BIG:
+		if (xs->cmdlen == 6) {
+			struct scsi_rw *rw = (struct scsi_rw *)xs->cmd;
+			bno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
+			bcnt = rw->length ? rw->length : 0x100;
+		} else {
+			struct scsi_rw_big *rwb = (struct scsi_rw_big *)xs->cmd;
+			bno = _4btol(rwb->addr);
+			bcnt = _2btol(rwb->length);
+		}
+
+		if (bno >= sc->sc_size || bno + bcnt > sc->sc_size) {
+			xs->error = XS_DRIVER_STUFFUP;
+			scsi_done(xs);
+			splx(s);
+			return COMPLETE;
+		}
+
+		mtx_enter(&sc->sc_freemtx);
+		bp = TAILQ_FIRST(&sc->sc_free);
+		TAILQ_REMOVE(&sc->sc_free, bp, hb_list);
+		mtx_leave(&sc->sc_freemtx);
+		splx(s);
+
+		bp->hb_xs = xs;
+		res = (vaddr_t)xs->data & PAGE_MASK;
+		if (xs->cmd->opcode == READ_COMMAND ||
+		    xs->cmd->opcode == READ_BIG) {
+			bp->hb_dst = (char *)HIMEM_LOW + res;
+			bp->hb_src = (char *)HIMEM_HIGH +
+			    ((bno & PDE_MASK) * DEV_BSIZE);
+		} else {
+			bp->hb_src = (char *)HIMEM_LOW + res;
+			bp->hb_dst = (char *)HIMEM_HIGH +
+			    ((bno & PDE_MASK) * DEV_BSIZE);
+		}
+
+		bp->hb_len = xs->datalen;
+		bp->hb_bno = bno;
+		bp->hb_flags = 0;
+
+		ptes = (u_int64_t *)bp + HIMEM_OFFSET;
+		for (va = (vaddr_t)xs->data - res,
+		    eva = (vaddr_t)xs->data + xs->datalen + PAGE_SIZE - 1;
+		    va < eva; va += PAGE_SIZE) {
+			pmap_extract(pmap_kernel(), va, &pa);
+			*ptes++ = pa | PG_KW | PG_U | PG_M | PG_V;
+		}
+
+		if (xs->flags & SCSI_POLL)
+			bp->hb_flags |= HIMEM_WAKE;
+
+		mtx_enter(&sc->sc_inmtx);
+		TAILQ_INSERT_TAIL(&sc->sc_in, bp, hb_list);
+		mtx_leave(&sc->sc_inmtx);
+		wakeup(&sc->sc_in);
+		if (xs->flags & SCSI_POLL) {
+			tsleep(bp, PRIBIO, "himem.poll", 0);
+			return COMPLETE;
+		} else
+			return SUCCESSFULLY_QUEUED;
+	}
+}
+
+int
+himem_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag,
+    struct proc *p)
+{
+	/* struct himem_softc *sc = link->adapter_softc; */
+
+	/* TODO implement set-rdonly */
+	return ENOTTY;
+}
+
+void
+himeminphys(struct buf *bp)
+{
+	if (bp->b_bcount > HIMEM_MAXPHYS)
+		bp->b_bcount = HIMEM_MAXPHYS;
+	minphys(bp);
+}
+
+void
+himem(void *v)
+{
+	struct scsibus_attach_args saa;
+	struct himem_softc *sc = v;
+	struct scsi_xfer *xs;
+	struct hibuf *bp;
+	int s, wake;
+
+	sc->sc_link.device = &himem_dev;
+	sc->sc_link.device_softc = sc;
+	sc->sc_link.adapter = &himem_switch;
+	sc->sc_link.adapter_softc = sc;
+	sc->sc_link.adapter_target = 1;
+	sc->sc_link.adapter_buswidth = 1;
+	sc->sc_link.openings = HIMEM_MAXCMDS;
+	bzero(&saa, sizeof(saa));
+	saa.saa_sc_link = &sc->sc_link;
+	config_found(&sc->sc_dev, &saa, scsiprint);
+
+	KERNEL_PROC_UNLOCK(curproc);
+
+	for (;;) {
+		mtx_enter(&sc->sc_inmtx);
+		while (TAILQ_EMPTY(&sc->sc_in))
+			msleep(&sc->sc_in, &sc->sc_inmtx, PRIBIO, "himem.sys", 0);
+
+		bp = TAILQ_FIRST(&sc->sc_in);
+		TAILQ_REMOVE(&sc->sc_in, bp, hb_list);
+		mtx_leave(&sc->sc_inmtx);
+
+		sc->sc_pdir[HIMEM_PDE] = bp->hb_pa | PG_KW | PG_U | PG_M | PG_V;
+		sc->sc_pdir[HIMEM_PDE+1] = PG_KW | PG_U | PG_M | PG_V | PG_PS |
+		    (0x100000000ULL + (bp->hb_bno & ~PDE_MASK) * DEV_BSIZE);
+		sc->sc_pdir[HIMEM_PDE+2] = sc->sc_pdir[HIMEM_PDE+1] + 0x200000;
+
+		himem_zefix(sc->sc_pdir, bp->hb_src, bp->hb_dst, bp->hb_len);
+
+		sc->sc_pdir[HIMEM_PDE] = 0;
+		sc->sc_pdir[HIMEM_PDE+1] = 0;
+
+		xs = bp->hb_xs;
+		xs->resid -= bp->hb_len;
+		xs->flags |= ITSDONE;
+		wake = bp->hb_flags & HIMEM_WAKE;
+		mtx_enter(&sc->sc_freemtx);
+		TAILQ_INSERT_HEAD(&sc->sc_free, bp, hb_list);
+		mtx_leave(&sc->sc_freemtx);
+
+		KERNEL_PROC_LOCK(curproc);
+		s = splbio();
+		scsi_done(xs);
+		splx(s);
+		if (wake)
+			wakeup(bp);
+		KERNEL_PROC_UNLOCK(curproc);
+	}
+}
Index: arch/i386/i386/locore.s
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/locore.s,v
retrieving revision 1.121
diff -u -r1.121 locore.s
--- arch/i386/i386/locore.s	28 Nov 2007 17:05:09 -0000	1.121
+++ arch/i386/i386/locore.s	9 May 2008 09:27:25 -0000
@@ -44,6 +44,7 @@
 #include "pctr.h"
 #include "ksyms.h"
 #include "acpi.h"
+#include "himem.h"
 
 #include <sys/errno.h>
 #include <sys/syscall.h>
@@ -1846,6 +1847,70 @@
 
 	popl	%ebx
 	popl	%edi
+	ret
+#endif
+
+#if NHIMEM > 0
+/*
+ * void
+ * himem_zefix(vaddr_t pdir, void *src, void *dst, int len)
+ *
+ * switch to PAE mode and copy some pages. come back before xmas.
+ * hafta be some serious splipi() or bad shitz would happenz.
+ *
+ */
+ENTRY(himem_zefix)
+#ifdef DDB
+	pushl	%ebp
+	movl	%esp,%ebp
+#endif
+	pushf
+	cli
+	pushl	%esi
+	pushl	%edi
+	movl	8(%ebp), %edi
+	movl	%cr3, %esi
+	addl	$KERNBASE, %esi
+	addl	$4*8, %edi	/* save current PD content */
+	movl	$8, %ecx
+	cld
+	rep
+	movsl
+	movl	8(%ebp), %esi	/* install our PDI */
+	movl	%cr3, %edi
+	addl	$KERNBASE, %edi
+	movl	$8, %ecx
+	cld
+	rep
+	movsl
+	movl	12(%ebp), %esi
+	movl	16(%ebp), %edi
+	movl	20(%ebp), %ecx
+	shrl	$2, %ecx
+	movl	%cr4, %eax
+	orl	$(CR4_PAE|CR4_PSE), %eax
+	movl	%eax, %cr4	/* also flushes the hell out of TLBs */
+	cld
+	rep
+	movsl
+	movl	%cr4, %eax
+	andl	$~(CR4_PAE|CR4_PSE), %eax
+	movl	%eax, %cr4	/* again flushes the hell out of TLBs */
+	xorl	%eax, %eax
+	movl	8(%ebp), %esi	/* restore original PD contents */
+	movl	%cr3, %edi
+	addl	$KERNBASE, %edi
+	addl	$4*8, %esi
+	movl	$8, %ecx
+	cld
+	rep
+	movsl
+	popl	%edi
+	popl	%esi
+	popf
+#ifdef DDB
+	leave
+#endif
 	ret
 #endif
 
Index: arch/i386/i386/machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.418
diff -u -r1.418 machdep.c
--- arch/i386/i386/machdep.c	18 Feb 2008 16:31:55 -0000	1.418
+++ arch/i386/i386/machdep.c	7 May 2008 12:55:43 -0000
@@ -234,7 +234,7 @@
 int	i386_has_xcrypt;
 
 bootarg_t *bootargp;
-paddr_t avail_end;
+u_int64_t avail_end, avail_end2;
 
 struct vm_map *exec_map = NULL;
 struct vm_map *phys_map = NULL;
@@ -2970,7 +2970,7 @@
 	 * account all the memory passed in the map from /boot
 	 * calculate avail_end and count the physmem.
 	 */
-	avail_end = 0;
+	avail_end = avail_end2 = 0;
 	physmem = 0;
 #ifdef DEBUG
 	printf("memmap:");
@@ -2986,6 +2986,8 @@
 #ifdef DEBUG
 				printf("-H");
 #endif
+				avail_end2 = MAX(avail_end2,
+				    trunc_page(im->addr + im->size));
 				continue;
 			}
 
Index: arch/i386/i386/pmap.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/pmap.c,v
retrieving revision 1.122
diff -u -r1.122 pmap.c
--- arch/i386/i386/pmap.c	13 Jan 2008 20:47:00 -0000	1.122
+++ arch/i386/i386/pmap.c	7 May 2008 11:53:12 -0000
@@ -189,10 +189,6 @@
  *   in the alternate PTE space (since that is determined by the
  *   entry in the PDP).
  *
- * - pvalloc_lock
- *   this lock protects the data structures which are used to manage
- *   the free list of pv_entry structures.
- *
  * - pmaps_lock
  *   this lock protects the list of active pmaps (headed by "pmaps").
  *   we lock it when adding or removing pmaps from this list.
@@ -203,7 +199,6 @@
  * locking data structures
  */
 
-struct simplelock pvalloc_lock;
 struct simplelock pmaps_lock;
 
 #define PMAP_MAP_TO_HEAD_LOCK()		/* null */
@@ -265,21 +260,6 @@
 static vaddr_t virtual_end;	/* VA of last free KVA */
 
 /*
- * pv_page management structures: locked by pvalloc_lock
- */
-
-TAILQ_HEAD(pv_pagelist, pv_page);
-static struct pv_pagelist pv_freepages;	/* list of pv_pages with free entries */
-static struct pv_pagelist pv_unusedpgs; /* list of unused pv_pages */
-static int pv_nfpvents;			/* # of free pv entries */
-static struct pv_page *pv_initpage;	/* bootstrap page from kernel_map */
-static vaddr_t pv_cachedva;		/* cached VA for later use */
-
-#define PVE_LOWAT (PVE_PER_PVPAGE / 2)	/* free pv_entry low water mark */
-#define PVE_HIWAT (PVE_LOWAT + (PVE_PER_PVPAGE * 2))
-					/* high water mark */
-
-/*
  * linked list of all non-kernel pmaps
  */
 
@@ -290,6 +270,7 @@
  */
 
 struct pool pmap_pmap_pool;
+struct pool pmap_pvpl;
 
 /*
  * MULTIPROCESSOR: special VA's/ PTE's are actually allocated inside a
@@ -321,19 +302,10 @@
  * local prototypes
  */
 
-struct pv_entry	*pmap_add_pvpage(struct pv_page *, boolean_t);
 struct vm_page	*pmap_alloc_ptp(struct pmap *, int, boolean_t, pt_entry_t);
-struct pv_entry	*pmap_alloc_pv(struct pmap *, int); /* see codes below */
-#define ALLOCPV_NEED	0	/* need PV now */
-#define ALLOCPV_TRY	1	/* just try to allocate */
-#define ALLOCPV_NONEED	2	/* don't need PV, just growing cache */
-struct pv_entry	*pmap_alloc_pvpage(struct pmap *, int);
 void		 pmap_enter_pv(struct vm_page *, struct pv_entry *,
     struct pmap *, vaddr_t, struct vm_page *);
-void		 pmap_free_pv(struct pmap *, struct pv_entry *);
 void		 pmap_free_pvs(struct pmap *, struct pv_entry *);
-void		 pmap_free_pv_doit(struct pv_entry *);
-void		 pmap_free_pvpage(void);
 struct vm_page	*pmap_get_ptp(struct pmap *, int, boolean_t);
 boolean_t	 pmap_is_curpmap(struct pmap *);
 boolean_t	 pmap_is_active(struct pmap *, int);
@@ -349,10 +321,6 @@
 #define PMAP_REMOVE_ALL		0
 #define PMAP_REMOVE_SKIPWIRED	1
 
-vaddr_t		 pmap_tmpmap_pa(paddr_t);
-pt_entry_t	*pmap_tmpmap_pvepte(struct pv_entry *);
-void		 pmap_tmpunmap_pa(void);
-void		 pmap_tmpunmap_pvepte(struct pv_entry *);
 void		 pmap_apte_flush(struct pmap *);
 void		pmap_unmap_ptes(struct pmap *);
 void		pmap_exec_account(struct pmap *, vaddr_t, pt_entry_t,
@@ -418,87 +386,6 @@
 	}
 }
 
-/*
- * pmap_tmpmap_pa: map a page in for tmp usage
- */
-
-vaddr_t
-pmap_tmpmap_pa(paddr_t pa)
-{
-#ifdef MULTIPROCESSOR
-	int id = cpu_number();
-#endif
-	pt_entry_t *ptpte = PTESLEW(ptp_pte, id);
-	caddr_t ptpva = VASLEW(ptpp, id);
-#if defined(DIAGNOSTIC)
-	if (*ptpte)
-		panic("pmap_tmpmap_pa: ptp_pte in use?");
-#endif
-	*ptpte = PG_V | PG_RW | pa;		/* always a new mapping */
-	return((vaddr_t)ptpva);
-}
-
-/*
- * pmap_tmpunmap_pa: unmap a tmp use page (undoes pmap_tmpmap_pa)
- */
-
-void
-pmap_tmpunmap_pa()
-{
-#ifdef MULTIPROCESSOR
-	int id = cpu_number();
-#endif
-	pt_entry_t *ptpte = PTESLEW(ptp_pte, id);
-	caddr_t ptpva = VASLEW(ptpp, id);
-#if defined(DIAGNOSTIC)
-	if (!pmap_valid_entry(*ptpte))
-		panic("pmap_tmpunmap_pa: our pte invalid?");
-#endif
-	*ptpte = 0;		/* zap! */
-	pmap_update_pg((vaddr_t)ptpva);
-#ifdef MULTIPROCESSOR
-	/*
-	 * No need for tlb shootdown here, since ptp_pte is per-CPU.
-	 */
-#endif
-}
-
-/*
- * pmap_tmpmap_pvepte: get a quick mapping of a PTE for a pv_entry
- *
- * => do NOT use this on kernel mappings [why?  because pv_ptp may be NULL]
- */
-
-pt_entry_t *
-pmap_tmpmap_pvepte(struct pv_entry *pve)
-{
-#ifdef DIAGNOSTIC
-	if (pve->pv_pmap == pmap_kernel())
-		panic("pmap_tmpmap_pvepte: attempt to map kernel");
-#endif
-
-	/* is it current pmap?  use direct mapping... */
-	if (pmap_is_curpmap(pve->pv_pmap))
-		return(vtopte(pve->pv_va));
-
-	return(((pt_entry_t *)pmap_tmpmap_pa(VM_PAGE_TO_PHYS(pve->pv_ptp)))
-	       + ptei((unsigned)pve->pv_va));
-}
-
-/*
- * pmap_tmpunmap_pvepte: release a mapping obtained with pmap_tmpmap_pvepte
- */
-
-void
-pmap_tmpunmap_pvepte(struct pv_entry *pve)
-{
-	/* was it current pmap?   if so, return */
-	if (pmap_is_curpmap(pve->pv_pmap))
-		return;
-
-	pmap_tmpunmap_pa();
-}
-
 void
 pmap_apte_flush(struct pmap *pmap)
 {
@@ -900,11 +787,8 @@
 	 * init the static-global locks and global lists.
 	 */
 
-	simple_lock_init(&pvalloc_lock);
 	simple_lock_init(&pmaps_lock);
 	LIST_INIT(&pmaps);
-	TAILQ_INIT(&pv_freepages);
-	TAILQ_INIT(&pv_unusedpgs);
 
 	/*
 	 * initialize the pmap pool.
@@ -913,6 +797,9 @@
 	pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl",
 	    &pool_allocator_nointr);
 
+	pool_init(&pmap_pvpl, sizeof(struct pv_entry), 0, 0, 0, "pvpl",
+	    &pool_allocator_nointr);
+
 	/*
 	 * ensure the TLB is sync'd with reality by flushing it...
 	 */
@@ -930,342 +817,21 @@
 pmap_init(void)
 {
 	/*
-	 * now we need to free enough pv_entry structures to allow us to get
-	 * the kmem_map allocated and inited (done after this function is
-	 * finished).  to do this we allocate one bootstrap page out of
-	 * kernel_map and use it to provide an initial pool of pv_entry
-	 * structures.   we never free this page.
-	 */
-
-	pv_initpage = (struct pv_page *) uvm_km_alloc(kernel_map, PAGE_SIZE);
-	if (pv_initpage == NULL)
-		panic("pmap_init: pv_initpage");
-	pv_cachedva = 0;   /* a VA we have allocated but not used yet */
-	pv_nfpvents = 0;
-	(void) pmap_add_pvpage(pv_initpage, FALSE);
-
-	/*
 	 * done: pmap module is up (and ready for business)
 	 */
 
 	pmap_initialized = TRUE;
 }
 
-/*
- * p v _ e n t r y   f u n c t i o n s
- */
-
-/*
- * pv_entry allocation functions:
- *   the main pv_entry allocation functions are:
- *     pmap_alloc_pv: allocate a pv_entry structure
- *     pmap_free_pv: free one pv_entry
- *     pmap_free_pvs: free a list of pv_entrys
- *
- * the rest are helper functions
- */
-
-/*
- * pmap_alloc_pv: inline function to allocate a pv_entry structure
- * => we lock pvalloc_lock
- * => if we fail, we call out to pmap_alloc_pvpage
- * => 3 modes:
- *    ALLOCPV_NEED   = we really need a pv_entry
- *    ALLOCPV_TRY    = we want a pv_entry
- *    ALLOCPV_NONEED = we are trying to grow our free list, don't really need
- *			one now
- *
- * "try" is for optional functions like pmap_copy().
- */
-
-struct pv_entry *
-pmap_alloc_pv(struct pmap *pmap, int mode)
-{
-	struct pv_page *pvpage;
-	struct pv_entry *pv;
-
-	simple_lock(&pvalloc_lock);
-
-	if (!TAILQ_EMPTY(&pv_freepages)) {
-		pvpage = TAILQ_FIRST(&pv_freepages);
-		pvpage->pvinfo.pvpi_nfree--;
-		if (pvpage->pvinfo.pvpi_nfree == 0) {
-			/* nothing left in this one? */
-			TAILQ_REMOVE(&pv_freepages, pvpage, pvinfo.pvpi_list);
-		}
-		pv = pvpage->pvinfo.pvpi_pvfree;
-#ifdef DIAGNOSTIC
-		if (pv == NULL)
-			panic("pmap_alloc_pv: pvpi_nfree off");
-#endif
-		pvpage->pvinfo.pvpi_pvfree = pv->pv_next;
-		pv_nfpvents--;  /* took one from pool */
-	} else {
-		pv = NULL;		/* need more of them */
-	}
-
-	/*
-	 * if below low water mark or we didn't get a pv_entry we try and
-	 * create more pv_entrys ...
-	 */
-
-	if (pv_nfpvents < PVE_LOWAT || pv == NULL) {
-		if (pv == NULL)
-			pv = pmap_alloc_pvpage(pmap, (mode == ALLOCPV_TRY) ?
-					       mode : ALLOCPV_NEED);
-		else
-			(void) pmap_alloc_pvpage(pmap, ALLOCPV_NONEED);
-	}
-
-	simple_unlock(&pvalloc_lock);
-	return(pv);
-}
-
-/*
- * pmap_alloc_pvpage: maybe allocate a new pvpage
- *
- * if need_entry is false: try and allocate a new pv_page
- * if need_entry is true: try and allocate a new pv_page and return a
- *	new pv_entry from it.
- *
- * => we assume that the caller holds pvalloc_lock
- */
-
-struct pv_entry *
-pmap_alloc_pvpage(struct pmap *pmap, int mode)
-{
-	struct vm_page *pg;
-	struct pv_page *pvpage;
-	struct pv_entry *pv;
-	int s;
-
-	/*
-	 * if we need_entry and we've got unused pv_pages, allocate from there
-	 */
-
-	if (mode != ALLOCPV_NONEED && !TAILQ_EMPTY(&pv_unusedpgs)) {
-
-		/* move it to pv_freepages list */
-		pvpage = TAILQ_FIRST(&pv_unusedpgs);
-		TAILQ_REMOVE(&pv_unusedpgs, pvpage, pvinfo.pvpi_list);
-		TAILQ_INSERT_HEAD(&pv_freepages, pvpage, pvinfo.pvpi_list);
-
-		/* allocate a pv_entry */
-		pvpage->pvinfo.pvpi_nfree--;	/* can't go to zero */
-		pv = pvpage->pvinfo.pvpi_pvfree;
-#ifdef DIAGNOSTIC
-		if (pv == NULL)
-			panic("pmap_alloc_pvpage: pvpi_nfree off");
-#endif
-		pvpage->pvinfo.pvpi_pvfree = pv->pv_next;
-
-		pv_nfpvents--;  /* took one from pool */
-		return(pv);
-	}
-
-	/*
-	 *  see if we've got a cached unmapped VA that we can map a page in.
-	 * if not, try to allocate one.
-	 */
-
-	s = splvm();   /* must protect kmem_map with splvm! */
-	if (pv_cachedva == 0) {
-		pv_cachedva = uvm_km_kmemalloc(kmem_map, NULL,
-		    NBPG, UVM_KMF_TRYLOCK|UVM_KMF_VALLOC);
-	}
-	splx(s);
-	if (pv_cachedva == 0)
-		return (NULL);
-
-	pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE);
-	if (pg == NULL)
-		return (NULL);
-
-	atomic_clearbits_int(&pg->pg_flags, PG_BUSY);
-
-	/*
-	 * add a mapping for our new pv_page and free its entries (save one!)
-	 *
-	 * NOTE: If we are allocating a PV page for the kernel pmap, the
-	 * pmap is already locked!  (...but entering the mapping is safe...)
-	 */
-
-	pmap_kenter_pa(pv_cachedva, VM_PAGE_TO_PHYS(pg),
-	    VM_PROT_READ|VM_PROT_WRITE);
-	pvpage = (struct pv_page *) pv_cachedva;
-	pv_cachedva = 0;
-	return (pmap_add_pvpage(pvpage, mode != ALLOCPV_NONEED));
-}
-
-/*
- * pmap_add_pvpage: add a pv_page's pv_entrys to the free list
- *
- * => caller must hold pvalloc_lock
- * => if need_entry is true, we allocate and return one pv_entry
- */
-
-struct pv_entry *
-pmap_add_pvpage(struct pv_page *pvp, boolean_t need_entry)
-{
-	int tofree, lcv;
-
-	/* do we need to return one? */
-	tofree = (need_entry) ? PVE_PER_PVPAGE - 1 : PVE_PER_PVPAGE;
-
-	pvp->pvinfo.pvpi_pvfree = NULL;
-	pvp->pvinfo.pvpi_nfree = tofree;
-	for (lcv = 0 ; lcv < tofree ; lcv++) {
-		pvp->pvents[lcv].pv_next = pvp->pvinfo.pvpi_pvfree;
-		pvp->pvinfo.pvpi_pvfree = &pvp->pvents[lcv];
-	}
-	if (need_entry)
-		TAILQ_INSERT_TAIL(&pv_freepages, pvp, pvinfo.pvpi_list);
-	else
-		TAILQ_INSERT_TAIL(&pv_unusedpgs, pvp, pvinfo.pvpi_list);
-	pv_nfpvents += tofree;
-	return((need_entry) ? &pvp->pvents[lcv] : NULL);
-}
-
-/*
- * pmap_free_pv_doit: actually free a pv_entry
- *
- * => do not call this directly!  instead use either
- *    1. pmap_free_pv ==> free a single pv_entry
- *    2. pmap_free_pvs => free a list of pv_entrys
- * => we must be holding pvalloc_lock
- */
-
-void
-pmap_free_pv_doit(struct pv_entry *pv)
-{
-	struct pv_page *pvp;
-
-	pvp = (struct pv_page*)trunc_page((vaddr_t)pv);
-	pv_nfpvents++;
-	pvp->pvinfo.pvpi_nfree++;
-
-	/* nfree == 1 => fully allocated page just became partly allocated */
-	if (pvp->pvinfo.pvpi_nfree == 1) {
-		TAILQ_INSERT_HEAD(&pv_freepages, pvp, pvinfo.pvpi_list);
-	}
-
-	/* free it */
-	pv->pv_next = pvp->pvinfo.pvpi_pvfree;
-	pvp->pvinfo.pvpi_pvfree = pv;
-
-	/*
-	 * are all pv_page's pv_entry's free?  move it to unused queue.
-	 */
-
-	if (pvp->pvinfo.pvpi_nfree == PVE_PER_PVPAGE) {
-		TAILQ_REMOVE(&pv_freepages, pvp, pvinfo.pvpi_list);
-		TAILQ_INSERT_HEAD(&pv_unusedpgs, pvp, pvinfo.pvpi_list);
-	}
-}
-
-/*
- * pmap_free_pv: free a single pv_entry
- *
- * => we gain the pvalloc_lock
- */
-
-void
-pmap_free_pv(struct pmap *pmap, struct pv_entry *pv)
-{
-	simple_lock(&pvalloc_lock);
-	pmap_free_pv_doit(pv);
-
-	/*
-	 * Can't free the PV page if the PV entries were associated with
-	 * the kernel pmap; the pmap is already locked.
-	 */
-	if (pv_nfpvents > PVE_HIWAT && TAILQ_FIRST(&pv_unusedpgs) != NULL &&
-	    pmap != pmap_kernel())
-		pmap_free_pvpage();
-
-	simple_unlock(&pvalloc_lock);
-}
-
-/*
- * pmap_free_pvs: free a list of pv_entrys
- *
- * => we gain the pvalloc_lock
- */
-
 void
 pmap_free_pvs(struct pmap *pmap, struct pv_entry *pvs)
 {
 	struct pv_entry *nextpv;
 
-	simple_lock(&pvalloc_lock);
-
 	for ( /* null */ ; pvs != NULL ; pvs = nextpv) {
 		nextpv = pvs->pv_next;
-		pmap_free_pv_doit(pvs);
-	}
-
-	/*
-	 * Can't free the PV page if the PV entries were associated with
-	 * the kernel pmap; the pmap is already locked.
-	 */
-	if (pv_nfpvents > PVE_HIWAT && TAILQ_FIRST(&pv_unusedpgs) != NULL &&
-	    pmap != pmap_kernel())
-		pmap_free_pvpage();
-
-	simple_unlock(&pvalloc_lock);
-}
-
-
-/*
- * pmap_free_pvpage: try and free an unused pv_page structure
- *
- * => assume caller is holding the pvalloc_lock and that
- *	there is a page on the pv_unusedpgs list
- * => if we can't get a lock on the kmem_map we try again later
- */
-
-void
-pmap_free_pvpage(void)
-{
-	int s;
-	struct vm_map *map;
-	struct vm_map_entry *dead_entries;
-	struct pv_page *pvp;
-
-	s = splvm(); /* protect kmem_map */
-	pvp = TAILQ_FIRST(&pv_unusedpgs);
-
-	/*
-	 * note: watch out for pv_initpage which is allocated out of
-	 * kernel_map rather than kmem_map.
-	 */
-
-	if (pvp == pv_initpage)
-		map = kernel_map;
-	else
-		map = kmem_map;
-	if (vm_map_lock_try(map)) {
-
-		/* remove pvp from pv_unusedpgs */
-		TAILQ_REMOVE(&pv_unusedpgs, pvp, pvinfo.pvpi_list);
-
-		/* unmap the page */
-		dead_entries = NULL;
-		uvm_unmap_remove(map, (vaddr_t)pvp, ((vaddr_t)pvp) + PAGE_SIZE,
-		    &dead_entries, NULL);
-		vm_map_unlock(map);
-
-		if (dead_entries != NULL)
-			uvm_unmap_detach(dead_entries, 0);
-
-		pv_nfpvents -= PVE_PER_PVPAGE;  /* update free count */
+		pool_put(&pmap_pvpl, pvs);
 	}
-
-	if (pvp == pv_initpage)
-		/* no more initpage, we've freed it */
-		pv_initpage = NULL;
-
-	splx(s);
 }
 
 /*
@@ -1991,7 +1557,7 @@
 	pmap_sync_flags_pte(pg, opte);
 	pve = pmap_remove_pv(pg, pmap, va);
 	if (pve)
-		pmap_free_pv(pmap, pve);
+		pool_put(&pmap_pvpl, pve);
 	return(TRUE);
 }
 
@@ -2704,7 +2270,7 @@
 
 	if (pg != NULL) {
 		if (pve == NULL) {
-			pve = pmap_alloc_pv(pmap, ALLOCPV_NEED);
+			pve = pool_get(&pmap_pvpl, PR_WAITOK);
 			if (pve == NULL) {
 				if (flags & PMAP_CANFAIL) {
 					/*
@@ -2722,7 +2288,7 @@
 
 		/* new mapping is not PG_PVLIST.   free pve if we've got one */
 		if (pve)
-			pmap_free_pv(pmap, pve);
+			pool_put(&pmap_pvpl, pve);
 	}
 
 enter_now:
Index: arch/i386/isa/isa_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/isa/isa_machdep.c,v
retrieving revision 1.61
diff -u -r1.61 isa_machdep.c
--- arch/i386/isa/isa_machdep.c	7 Sep 2007 15:00:19 -0000	1.61
+++ arch/i386/isa/isa_machdep.c	7 May 2008 12:55:43 -0000
@@ -105,7 +105,7 @@
 
 #include "isadma.h"
 
-extern	paddr_t avail_end;
+extern	u_int64_t avail_end;
 
 #define	IDTVEC(name)	__CONCAT(X,name)
 /* default interrupt vector table entries */
Index: arch/i386/pci/pci_addr_fixup.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/pci/pci_addr_fixup.c,v
retrieving revision 1.21
diff -u -r1.21 pci_addr_fixup.c
--- arch/i386/pci/pci_addr_fixup.c	20 Feb 2007 21:15:01 -0000	1.21
+++ arch/i386/pci/pci_addr_fixup.c	7 May 2008 12:55:43 -0000
@@ -80,7 +80,7 @@
 void
 pci_addr_fixup(struct pcibios_softc *sc, pci_chipset_tag_t pc, int maxbus)
 {
-	extern paddr_t avail_end;
+	extern u_int64_t avail_end;
 	const char *verbose_header = 
 		"[%s]-----------------------\n"
 		"  device vendor product\n"
@@ -136,8 +136,9 @@
 		start = PCIADDR_ISAMEM_RESERVE;
 	sc->mem_alloc_start = (start + 0x100000 + 1) & ~(0x100000 - 1);
 	sc->port_alloc_start = PCIADDR_ISAPORT_RESERVE;
-	PCIBIOS_PRINTV((" Physical memory end: 0x%08x\n PCI memory mapped I/O "
-	    "space start: 0x%08x\n", avail_end, sc->mem_alloc_start));
+	PCIBIOS_PRINTV((" Physical memory end: 0x%08llx\n"
+	    "  PCI memory mapped I/O space start: 0x%08x\n",
+	    avail_end, sc->mem_alloc_start));
 
 	/* 
 	 * 4. do fixup 
Index: kern/kern_exit.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.72
diff -u -r1.72 kern_exit.c
--- kern/kern_exit.c	10 Oct 2007 15:53:53 -0000	1.72
+++ kern/kern_exit.c	7 May 2008 11:55:28 -0000
@@ -233,6 +233,11 @@
 		systrace_exit(p);
 #endif
 	/*
+	 * unmap all user space now as we will not need it anymore
+	 */
+	uvmspace_unmap(p->p_vmspace);
+
+	/*
 	 * NOTE: WE ARE NO LONGER ALLOWED TO SLEEP!
 	 */
 	p->p_stat = SDEAD;
Index: kern/kern_malloc.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_malloc.c,v
retrieving revision 1.74
diff -u -r1.74 kern_malloc.c
--- kern/kern_malloc.c	21 Feb 2008 10:40:48 -0000	1.74
+++ kern/kern_malloc.c	7 May 2008 11:51:50 -0000
@@ -1,7 +1,7 @@
 /*	$OpenBSD: kern_malloc.c,v 1.74 2008/02/21 10:40:48 kettenis Exp $	*/
-/*	$NetBSD: kern_malloc.c,v 1.15.4.2 1996/06/13 17:10:56 cgd Exp $	*/
 
 /*
+ * Copyright (c) 2008 Michael Shalayeff
  * Copyright (c) 1987, 1991, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -39,6 +39,7 @@
 #include <sys/systm.h>
 #include <sys/sysctl.h>
 #include <sys/time.h>
+#include <sys/pool.h>
 #include <sys/rwlock.h>
 
 #include <uvm/uvm_extern.h>
@@ -74,6 +75,8 @@
 #endif
 u_int	nkmempages_max = 0;
 
+struct pool mallocpl[MINBUCKET + 16];
+char	mallocplnames[MINBUCKET + 16][8];	/* wchan for pool */
 struct kmembuckets bucket[MINBUCKET + 16];
 struct kmemstats kmemstats[M_LAST];
 struct kmemusage *kmemusage;
@@ -133,6 +136,77 @@
 struct timeval malloc_lasterr;
 #endif
 
+void	*malloc_page_alloc(struct pool *, int);
+void	malloc_page_free(struct pool *, void *);
+struct pool_allocator pool_allocator_malloc = {
+	malloc_page_alloc, malloc_page_free, 0,
+};
+
+void *
+malloc_page_alloc(struct pool *pp, int flags)
+{
+#if 0
+	struct kmembuckets *kbp;
+	struct kmemusage *kup;
+	int indx;
+
+	void *v = (void *)uvm_km_kmemalloc(kmem_map, uvmexp.kmem_object,
+	    PAGE_SIZE, ((flags & M_NOWAIT) ? UVM_KMF_NOWAIT : 0) |
+	    ((flags & M_CANFAIL) ? UVM_KMF_CANFAIL : 0));
+
+	kup = btokup(v);
+	indx = BUCKETINDX(pp->pr_size);
+	kup->ku_indx = indx;
+#ifdef KMEMSTATS
+	kbp = &bucket[indx];
+	kbp->kb_totalfree += kbp->kb_elmpercl;
+	kbp->kb_total += kbp->kb_elmpercl;
+#endif
+#else
+	void *v = uvm_km_getpage(flags & M_NOWAIT? 0 : 1);
+	struct vm_page *pg;
+	paddr_t pa;
+
+	if (!pmap_extract(pmap_kernel(), (vaddr_t)v, &pa))
+		panic("malloc_page_alloc: pmap_extract failed");
+
+	pg = PHYS_TO_VM_PAGE(pa);
+	if (pg == NULL)
+		panic("malloc_page_alloc: no page");
+	pg->wire_count = BUCKETINDX(pp->pr_size);
+#endif
+	return v;
+}
+
+void
+malloc_page_free(struct pool *pp, void *v)
+{
+#if 0
+	struct kmembuckets *kbp;
+	struct kmemusage *kup = btokup(v);
+
+	kbp = &bucket[kup->ku_indx];
+	uvm_km_free(kmem_map, (vaddr_t)v, PAGE_SIZE);
+	kup->ku_indx = 0;
+#ifdef KMEMSTATS
+	kbp->kb_totalfree -= kbp->kb_elmpercl;
+	kbp->kb_total -= kbp->kb_elmpercl;
+#endif
+#else
+	struct vm_page *pg;
+	paddr_t pa;
+
+	if (!pmap_extract(pmap_kernel(), (vaddr_t)v, &pa))
+		panic("malloc_page_free: pmap_extract failed");
+
+	pg = PHYS_TO_VM_PAGE(pa);
+	if (pg == NULL)
+		panic("malloc_page_free: no page");
+	pg->wire_count = 1;
+	uvm_km_putpage(v);
+#endif
+}
+
 /*
  * Allocate a block of memory
  */
@@ -141,15 +215,9 @@
 {
 	struct kmembuckets *kbp;
 	struct kmemusage *kup;
-	struct freelist *freep;
 	long indx, npg, allocsize;
 	int s;
-	caddr_t va, cp, savedlist;
-#ifdef DIAGNOSTIC
-	int32_t *end, *lp;
-	int copysize;
-	char *savedtype;
-#endif
+	caddr_t va;
 #ifdef KMEMSTATS
 	struct kmemstats *ksp = &kmemstats[type];
 
@@ -161,7 +229,7 @@
 	if (debug_malloc(size, type, flags, (void **)&va)) {
 		if ((flags & M_ZERO) && va != NULL)
 			memset(va, 0, size);
-		return (va);
+		return ((void *) va);
 	}
 #endif
 
@@ -180,29 +248,22 @@
 	indx = BUCKETINDX(size);
 	kbp = &bucket[indx];
 	s = splvm();
+	if (size > MAXALLOCSAVE) {
 #ifdef KMEMSTATS
-	while (ksp->ks_memuse >= ksp->ks_limit) {
-		if (flags & M_NOWAIT) {
-			splx(s);
-			return (NULL);
+		while (ksp->ks_memuse >= ksp->ks_limit) {
+			if (flags & M_NOWAIT) {
+				splx(s);
+				return ((void *) NULL);
+			}
+			if (ksp->ks_limblocks < 65535)
+				ksp->ks_limblocks++;
+			tsleep(ksp, PSWP+2, memname[type], 0);
 		}
-		if (ksp->ks_limblocks < 65535)
-			ksp->ks_limblocks++;
-		tsleep(ksp, PSWP+2, memname[type], 0);
-	}
-	ksp->ks_size |= 1 << indx;
-#endif
-#ifdef DIAGNOSTIC
-	copysize = 1 << indx < MAX_COPY ? 1 << indx : MAX_COPY;
 #endif
-	if (kbp->kb_next == NULL) {
-		if (size > MAXALLOCSAVE)
-			allocsize = round_page(size);
-		else
-			allocsize = 1 << indx;
-		npg = atop(round_page(allocsize));
+		allocsize = round_page(size);
+		npg = atop(allocsize);
 		va = (caddr_t) uvm_km_kmemalloc(kmem_map, NULL,
-		    (vsize_t)ptoa(npg), 
+		    (vsize_t)ptoa(npg),
 		    ((flags & M_NOWAIT) ? UVM_KMF_NOWAIT : 0) |
 		    ((flags & M_CANFAIL) ? UVM_KMF_CANFAIL : 0));
 		if (va == NULL) {
@@ -220,121 +281,41 @@
 			return (NULL);
 		}
 #ifdef KMEMSTATS
-		kbp->kb_total += kbp->kb_elmpercl;
+		kbp->kb_total++;
 #endif
 		kup = btokup(va);
 		kup->ku_indx = indx;
-		if (allocsize > MAXALLOCSAVE) {
-			kup->ku_pagecnt = npg;
-#ifdef KMEMSTATS
-			ksp->ks_memuse += allocsize;
-#endif
-			goto out;
-		}
+		kup->ku_pagecnt = npg;
 #ifdef KMEMSTATS
-		kup->ku_freecnt = kbp->kb_elmpercl;
-		kbp->kb_totalfree += kbp->kb_elmpercl;
+		kbp->kb_calls++;
+		ksp->ks_memuse += allocsize;
+		ksp->ks_size |= 1 << indx;
+		ksp->ks_inuse++;
+		ksp->ks_calls++;
+		if (ksp->ks_memuse > ksp->ks_maxused)
+			ksp->ks_maxused = ksp->ks_memuse;
 #endif
-		/*
-		 * Just in case we blocked while allocating memory,
-		 * and someone else also allocated memory for this
-		 * bucket, don't assume the list is still empty.
-		 */
-		savedlist = kbp->kb_next;
-		kbp->kb_next = cp = va + (npg * PAGE_SIZE) - allocsize;
-		for (;;) {
-			freep = (struct freelist *)cp;
-#ifdef DIAGNOSTIC
-			/*
-			 * Copy in known text to detect modification
-			 * after freeing.
-			 */
-			end = (int32_t *)&cp[copysize];
-			for (lp = (int32_t *)cp; lp < end; lp++)
-				*lp = WEIRD_ADDR;
-			freep->type = M_FREE;
-#endif /* DIAGNOSTIC */
-			if (cp <= va)
-				break;
-			cp -= allocsize;
-			freep->next = cp;
-		}
-		freep->next = savedlist;
-		if (savedlist == NULL)
-			kbp->kb_last = (caddr_t)freep;
-	}
-	va = kbp->kb_next;
-	kbp->kb_next = ((struct freelist *)va)->next;
-#ifdef DIAGNOSTIC
-	freep = (struct freelist *)va;
-	savedtype = (unsigned)freep->type < M_LAST ?
-		memname[freep->type] : "???";
-	if (kbp->kb_next) {
-		int rv;
-		vaddr_t addr = (vaddr_t)kbp->kb_next;
-
-		vm_map_lock(kmem_map);
-		rv = uvm_map_checkprot(kmem_map, addr,
-		    addr + sizeof(struct freelist), VM_PROT_WRITE);
-		vm_map_unlock(kmem_map);
-
-		if (!rv)  {
-		printf("%s %d of object %p size 0x%lx %s %s (invalid addr %p)\n",
-			"Data modified on freelist: word", 
-			(int32_t *)&kbp->kb_next - (int32_t *)kbp, va, size,
-			"previous type", savedtype, kbp->kb_next);
-		kbp->kb_next = NULL;
-		}
+		splx(s);
+		if ((flags & M_ZERO) && va != NULL)
+			memset(va, 0, size);
+		return ((void *) va);
 	}
 
-	/* Fill the fields that we've used with WEIRD_ADDR */
-#if BYTE_ORDER == BIG_ENDIAN
-	freep->type = WEIRD_ADDR >> 16;
-#endif
-#if BYTE_ORDER == LITTLE_ENDIAN
-	freep->type = (short)WEIRD_ADDR;
-#endif
-	end = (int32_t *)&freep->next +
-	    (sizeof(freep->next) / sizeof(int32_t));
-	for (lp = (int32_t *)&freep->next; lp < end; lp++)
-		*lp = WEIRD_ADDR;
-
-	/* and check that the data hasn't been modified. */
-	end = (int32_t *)&va[copysize];
-	for (lp = (int32_t *)va; lp < end; lp++) {
-		if (*lp == WEIRD_ADDR)
-			continue;
-		printf("%s %d of object %p size 0x%lx %s %s (0x%x != 0x%x)\n",
-			"Data modified on freelist: word", lp - (int32_t *)va,
-			va, size, "previous type", savedtype, *lp, WEIRD_ADDR);
-		break;
+	va = pool_get(&mallocpl[indx], PR_LIMITFAIL |
+	    (flags & M_NOWAIT? 0 : PR_WAITOK));
+	if (!va && (flags & (M_NOWAIT|M_CANFAIL)) == 0)
+		panic("malloc: out of space in kmem pool");
+#ifdef KMEMSTATS
+	if (va) {
+		ksp->ks_size |= 1 << indx;
+		ksp->ks_inuse++;
+		ksp->ks_calls++;
 	}
-
-	freep->spare0 = 0;
-#endif /* DIAGNOSTIC */
-#ifdef KMEMSTATS
-	kup = btokup(va);
-	if (kup->ku_indx != indx)
-		panic("malloc: wrong bucket");
-	if (kup->ku_freecnt == 0)
-		panic("malloc: lost data");
-	kup->ku_freecnt--;
-	kbp->kb_totalfree--;
-	ksp->ks_memuse += 1 << indx;
-out:
-	kbp->kb_calls++;
-	ksp->ks_inuse++;
-	ksp->ks_calls++;
-	if (ksp->ks_memuse > ksp->ks_maxused)
-		ksp->ks_maxused = ksp->ks_memuse;
-#else
-out:
 #endif
 	splx(s);
-
 	if ((flags & M_ZERO) && va != NULL)
 		memset(va, 0, size);
-	return (va);
+	return ((void *) va);
 }
 
 /*
@@ -345,13 +326,12 @@
 {
 	struct kmembuckets *kbp;
 	struct kmemusage *kup;
-	struct freelist *freep;
+	struct vm_page *pg;
+	paddr_t pa;
 	long size;
 	int s;
 #ifdef DIAGNOSTIC
-	caddr_t cp;
-	int32_t *end, *lp;
-	long alloc, copysize;
+	long alloc;
 #endif
 #ifdef KMEMSTATS
 	struct kmemstats *ksp = &kmemstats[type];
@@ -362,30 +342,24 @@
 		return;
 #endif
 
-#ifdef DIAGNOSTIC
-	if (addr < (void *)kmembase || addr >= (void *)kmemlimit)
-		panic("free: non-malloced addr %p type %s", addr,
-		    memname[type]);
-#endif
-
-	kup = btokup(addr);
-	size = 1 << kup->ku_indx;
-	kbp = &bucket[kup->ku_indx];
 	s = splvm();
+	if (addr >= (void *)kmembase && addr < (void *)kmemlimit) {
+		kup = btokup(addr);
+		size = 1 << kup->ku_indx;
+		kbp = &bucket[kup->ku_indx];
 #ifdef DIAGNOSTIC
-	/*
-	 * Check for returns of data that do not point to the
-	 * beginning of the allocation.
-	 */
-	if (size > PAGE_SIZE)
-		alloc = addrmask[BUCKETINDX(PAGE_SIZE)];
-	else
-		alloc = addrmask[kup->ku_indx];
-	if (((u_long)addr & alloc) != 0)
-		panic("free: unaligned addr %p, size %ld, type %s, mask %ld",
-			addr, size, memname[type], alloc);
+		/*
+		 * Check for returns of data that do not point to the
+		 * beginning of the allocation.
+		 */
+		if (size > PAGE_SIZE)
+			alloc = addrmask[BUCKETINDX(PAGE_SIZE)];
+		else
+			alloc = addrmask[kup->ku_indx];
+		if (((u_long)addr & alloc) != 0)
+			panic("free: unaligned addr %p, size %ld, type %s, mask %ld",
+			    addr, size, memname[type], alloc);
 #endif /* DIAGNOSTIC */
-	if (size > MAXALLOCSAVE) {
 		uvm_km_free(kmem_map, (vaddr_t)addr, ptoa(kup->ku_pagecnt));
 #ifdef KMEMSTATS
 		size = kup->ku_pagecnt << PGSHIFT;
@@ -396,59 +370,26 @@
 		    ksp->ks_memuse < ksp->ks_limit)
 			wakeup(ksp);
 		ksp->ks_inuse--;
-		kbp->kb_total -= 1;
+		kbp->kb_total--;
 #endif
 		splx(s);
 		return;
 	}
-	freep = (struct freelist *)addr;
+	if (!pmap_extract(pmap_kernel(), (vaddr_t)addr, &pa))
+		panic("free: pmap_extract failed");
+	pg = PHYS_TO_VM_PAGE(pa);
+	if (pg == NULL)
+		panic("free: no page");
 #ifdef DIAGNOSTIC
-	/*
-	 * Check for multiple frees. Use a quick check to see if
-	 * it looks free before laboriously searching the freelist.
-	 */
-	if (freep->spare0 == WEIRD_ADDR) {
-		for (cp = kbp->kb_next; cp;
-		    cp = ((struct freelist *)cp)->next) {
-			if (addr != cp)
-				continue;
-			printf("multiply freed item %p\n", addr);
-			panic("free: duplicated free");
-		}
-	}
-	/*
-	 * Copy in known text to detect modification after freeing
-	 * and to make it look free. Also, save the type being freed
-	 * so we can list likely culprit if modification is detected
-	 * when the object is reallocated.
-	 */
-	copysize = size < MAX_COPY ? size : MAX_COPY;
-	end = (int32_t *)&((caddr_t)addr)[copysize];
-	for (lp = (int32_t *)addr; lp < end; lp++)
-		*lp = WEIRD_ADDR;
-	freep->type = type;
-#endif /* DIAGNOSTIC */
+	if (pg->pg_flags & PQ_FREE)
+		panic("free: page %p is free", pg);
+	if (pg->wire_count < MINBUCKET || (1 << pg->wire_count) > MAXALLOCSAVE)
+		panic("free: invalid page bucket %d", pg->wire_count);
+#endif
+	pool_put(&mallocpl[pg->wire_count], addr);
 #ifdef KMEMSTATS
-	kup->ku_freecnt++;
-	if (kup->ku_freecnt >= kbp->kb_elmpercl) {
-		if (kup->ku_freecnt > kbp->kb_elmpercl)
-			panic("free: multiple frees");
-		else if (kbp->kb_totalfree > kbp->kb_highwat)
-			kbp->kb_couldfree++;
-	}
-	kbp->kb_totalfree++;
-	ksp->ks_memuse -= size;
-	if (ksp->ks_memuse + size >= ksp->ks_limit &&
-	    ksp->ks_memuse < ksp->ks_limit)
-		wakeup(ksp);
 	ksp->ks_inuse--;
 #endif
-	if (kbp->kb_next == NULL)
-		kbp->kb_next = addr;
-	else
-		((struct freelist *)kbp->kb_last)->next = addr;
-	freep->next = NULL;
-	kbp->kb_last = addr;
 	splx(s);
 }
 
@@ -507,9 +448,7 @@
 kmeminit(void)
 {
 	vaddr_t base, limit;
-#ifdef KMEMSTATS
-	long indx;
-#endif
+	int i;
 
 #ifdef DIAGNOSTIC
 	if (sizeof(struct freelist) > (1 << MINBUCKET))
@@ -529,16 +468,26 @@
 	kmemlimit = (char *)limit;
 	kmemusage = (struct kmemusage *) uvm_km_zalloc(kernel_map,
 		(vsize_t)(nkmempages * sizeof(struct kmemusage)));
+	/*
+	 * init all the sub-page pools
+	 */
+	for (i = MINBUCKET; (1 << i) <= MAXALLOCSAVE; i++) {
+		snprintf(mallocplnames[i], sizeof(mallocplnames[i]),
+		    "kmem%d", i);
+		pool_init(&mallocpl[i], 1 << i, 1 << i, 0, PR_LIMITFAIL,
+		    mallocplnames[i], &pool_allocator_malloc);
+	}
+
 #ifdef KMEMSTATS
-	for (indx = 0; indx < MINBUCKET + 16; indx++) {
-		if (1 << indx >= PAGE_SIZE)
-			bucket[indx].kb_elmpercl = 1;
+	for (i = 0; i < MINBUCKET + 16; i++) {
+		if (1 << i >= PAGE_SIZE)
+			bucket[i].kb_elmpercl = 1;
 		else
-			bucket[indx].kb_elmpercl = PAGE_SIZE / (1 << indx);
-		bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl;
+			bucket[i].kb_elmpercl = PAGE_SIZE / (1 << i);
+		bucket[i].kb_highwat = 5 * bucket[i].kb_elmpercl;
 	}
-	for (indx = 0; indx < M_LAST; indx++)
-		kmemstats[indx].ks_limit = nkmempages * PAGE_SIZE * 6 / 10;
+	for (i = 0; i < M_LAST; i++)
+		kmemstats[i].ks_limit = nkmempages * PAGE_SIZE * 6 / 10;
 #endif
 #ifdef MALLOC_DEBUG
 	debug_malloc_init();
@@ -579,7 +528,6 @@
 
 	case KERN_MALLOC_BUCKET:
 		bcopy(&bucket[BUCKETINDX(name[1])], &kb, sizeof(kb));
-		kb.kb_next = kb.kb_last = 0;
 		return (sysctl_rdstruct(oldp, oldlenp, newp, &kb, sizeof(kb)));
 	case KERN_MALLOC_KMEMSTATS:
 #ifdef KMEMSTATS
@@ -607,8 +555,9 @@
 			}
 			memall = malloc(totlen + M_LAST, M_SYSCTL,
 			    M_WAITOK|M_ZERO);
+			bzero(memall, totlen + M_LAST);
 			for (siz = 0, i = 0; i < M_LAST; i++) {
-				snprintf(memall + siz, 
+				snprintf(memall + siz,
 				    totlen + M_LAST - siz,
 				    "%s,", memname[i] ? memname[i] : "");
 				siz += strlen(memall + siz);
@@ -666,7 +615,7 @@
 
 		(*pr)("%15s %5ld %6ldK %7ldK %6ldK %9ld %8d %8d\n",
 		    memname[i], km->ks_inuse, km->ks_memuse / 1024,
-		    km->ks_maxused / 1024, km->ks_limit / 1024, 
+		    km->ks_maxused / 1024, km->ks_limit / 1024,
 		    km->ks_calls, km->ks_limblocks, km->ks_mapblocks);
 	}
 #else
Index: sys/malloc.h
===================================================================
RCS file: /cvs/src/sys/sys/malloc.h,v
retrieving revision 1.90
diff -u -r1.90 malloc.h
--- sys/malloc.h	28 Nov 2007 23:37:34 -0000	1.90
+++ sys/malloc.h	7 May 2008 11:51:50 -0000
@@ -348,8 +348,7 @@
  * Set of buckets for each size of memory block that is retained
  */
 struct kmembuckets {
-	caddr_t   kb_next;	/* list of free blocks */
-	caddr_t   kb_last;	/* last free block */
+	caddr_t   kb_dummy[2];
 	u_int64_t kb_calls;	/* total calls to allocate this size */
 	u_int64_t kb_total;	/* total number of blocks allocated */
 	u_int64_t kb_totalfree;	/* # of free elements in this bucket */
Index: sys/param.h
===================================================================
RCS file: /cvs/src/sys/sys/param.h,v
retrieving revision 1.74
diff -u -r1.74 param.h
--- sys/param.h	10 Mar 2008 17:15:33 -0000	1.74
+++ sys/param.h	7 May 2008 11:51:50 -0000
@@ -212,8 +212,8 @@
  * Constraints: PAGE_SIZE <= MAXALLOCSAVE <= 2 ** (MINBUCKET + 14), and
  * MAXALLOCSIZE must be a power of two.
  */
-#define MINBUCKET	4		/* 4 => min allocation of 16 bytes */
-#define MAXALLOCSAVE	(2 * PAGE_SIZE)
+#define MINBUCKET	(sizeof(long) == 4? 4 : 5)
+#define MAXALLOCSAVE	(PAGE_SIZE)
 
 /*
  * Scale factor for scaled integers used to count %cpu time and load avgs.
Index: uvm/uvm_amap.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_amap.c,v
retrieving revision 1.40
diff -u -r1.40 uvm_amap.c
--- uvm/uvm_amap.c	7 Sep 2007 15:00:20 -0000	1.40
+++ uvm/uvm_amap.c	7 May 2008 11:59:30 -0000
@@ -369,6 +369,9 @@
 	 * XXXCDC: could we take advantage of a kernel realloc()?  
 	 */
 
+	if (slotneed >= UVM_AMAP_LARGE)
+		return E2BIG;
+
 	slotalloc = malloc_roundup(slotneed * sizeof(int)) / sizeof(int);
 #ifdef UVM_AMAP_PPREF
 	newppref = NULL;
Index: uvm/uvm_extern.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_extern.h,v
retrieving revision 1.68
diff -u -r1.68 uvm_extern.h
--- uvm/uvm_extern.h	29 Nov 2007 00:26:41 -0000	1.68
+++ uvm/uvm_extern.h	7 May 2008 11:55:28 -0000
@@ -525,6 +525,7 @@
 				vaddr_t, vaddr_t, boolean_t, boolean_t);
 void			uvmspace_exec(struct proc *, vaddr_t, vaddr_t);
 struct vmspace		*uvmspace_fork(struct vmspace *);
+void			uvmspace_unmap(struct vmspace *);
 void			uvmspace_free(struct vmspace *);
 void			uvmspace_share(struct proc *, struct proc *);
 void			uvmspace_unshare(struct proc *);
Index: uvm/uvm_init.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_init.c,v
retrieving revision 1.16
diff -u -r1.16 uvm_init.c
--- uvm/uvm_init.c	18 Jun 2007 21:51:15 -0000	1.16
+++ uvm/uvm_init.c	8 May 2008 19:59:40 -0000
@@ -48,6 +48,7 @@
 #include <sys/proc.h>
 #include <sys/malloc.h>
 #include <sys/vnode.h>
+#include <sys/kthread.h>
 
 #include <uvm/uvm.h>
 
@@ -125,7 +126,11 @@
 	 * kernel memory allocator (malloc) can be used.
 	 */
 
+	uvm_km_page_init();
 	kmeminit();
+#ifndef PMAP_DIRECT
+	kthread_create_deferred(uvm_km_createthread, NULL);
+#endif
 
 	/*
 	 * step 7: init all pagers and the pager_map.
@@ -148,8 +153,6 @@
 	uvm_page_rehash();
 	uao_create(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
 	    UAO_FLAG_KERNSWAP);
-
-	uvm_km_page_init();
 
 	/*
 	 * reserve some unmapped space for malloc/pool use after free usage
Index: uvm/uvm_km.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_km.c,v
retrieving revision 1.66
diff -u -r1.66 uvm_km.c
--- uvm/uvm_km.c	15 Dec 2007 03:42:57 -0000	1.66
+++ uvm/uvm_km.c	8 May 2008 19:59:22 -0000
@@ -791,9 +791,6 @@
 	struct km_page *next;
 } *uvm_km_pages_head;
 
-void uvm_km_createthread(void *);
-void uvm_km_thread(void *);
-
 /*
  * Allocate the initial reserve, and create the thread which will
  * keep the reserve full.  For bootstrapping, we allocate more than
@@ -817,7 +814,7 @@
 	}
 
 	for (i = 0; i < uvm_km_pages_lowat * 4; i++) {
-		page = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE);
+		page = (void *)uvm_km_kmemalloc(kernel_map, NULL, PAGE_SIZE, 0);
 		page->next = uvm_km_pages_head;
 		uvm_km_pages_head = page;
 	}
@@ -826,8 +823,6 @@
 	/* tone down if really high */
 	if (uvm_km_pages_lowat > 512)
 		uvm_km_pages_lowat = 512;
-
-	kthread_create_deferred(uvm_km_createthread, NULL);
 }
 
 void
@@ -852,7 +847,8 @@
 		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);
+			page = (void *)uvm_km_kmemalloc(kernel_map, NULL,
+			    PAGE_SIZE, 0);
 			if (i == 0)
 				head = tail = page;
 			if (page == NULL)
Index: uvm/uvm_km.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_km.h,v
retrieving revision 1.9
diff -u -r1.9 uvm_km.h
--- uvm/uvm_km.h	11 Apr 2007 12:10:42 -0000	1.9
+++ uvm/uvm_km.h	7 May 2008 11:53:12 -0000
@@ -50,6 +50,8 @@
 
 void uvm_km_init(vaddr_t, vaddr_t);
 void uvm_km_page_init(void);
+void uvm_km_createthread(void *);
+void uvm_km_thread(void *);
 void uvm_km_pgremove(struct uvm_object *, vaddr_t, vaddr_t);
 void uvm_km_pgremove_intrsafe(vaddr_t, vaddr_t);
 
Index: uvm/uvm_map.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.c,v
retrieving revision 1.99
diff -u -r1.99 uvm_map.c
--- uvm/uvm_map.c	15 Sep 2007 10:10:37 -0000	1.99
+++ uvm/uvm_map.c	8 May 2008 21:26:48 -0000
@@ -834,10 +834,8 @@
 
 		if (prev_entry->aref.ar_amap) {
 			error = amap_extend(prev_entry, size);
-			if (error) {
-				vm_map_unlock(map);
-				return (error);
-			}
+			if (error)
+				goto step3;
 		}
 
 		UVMCNT_INCR(map_backmerge);
@@ -3263,6 +3261,37 @@
 
 		uvmspace_free(ovm);
 	}
+}
+
+/*
+ * uvmspace_unmap: unmap all mappings in vmspace
+ * - XXX: no locking on vmspace
+ */
+
+void
+uvmspace_unmap(struct vmspace *vm)
+{ 
+	vm_map_entry_t dead_entries;
+	UVMHIST_FUNC("uvmspace_unmap"); UVMHIST_CALLED(maphist);
+
+	UVMHIST_LOG(maphist,"(vm=0x%x) ref=%d", vm, vm->vm_refcnt,0,0);
+	if (vm->vm_refcnt == 1) {
+		/*
+		 * lock the map, to wait out all other references to it. delete
+		 * all of the mappings and pages they hold, then call the pmap
+		 * module to reclaim anything left.
+		 */
+		vm_map_lock(&vm->vm_map);
+		if (vm->vm_map.nentries) {
+			uvm_unmap_remove(&vm->vm_map,
+			    vm->vm_map.min_offset, vm->vm_map.max_offset,
+			    &dead_entries, NULL);
+			if (dead_entries != NULL)
+				uvm_unmap_detach(dead_entries, 0);
+		}
+		vm_map_unlock(&vm->vm_map);
+	}
+	UVMHIST_LOG(maphist,"<- done", 0,0,0,0);
 }
 
 /*

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic