summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_jumbo.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/uipc_jumbo.c')
-rw-r--r--sys/kern/uipc_jumbo.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/sys/kern/uipc_jumbo.c b/sys/kern/uipc_jumbo.c
new file mode 100644
index 0000000..4625752
--- /dev/null
+++ b/sys/kern/uipc_jumbo.c
@@ -0,0 +1,252 @@
+/*-
+ * Copyright (c) 1997, Duke University
+ * All rights reserved.
+ *
+ * Author:
+ * Andrew Gallatin <gallatin@cs.duke.edu>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgements:
+ * This product includes software developed by Duke University
+ * 4. The name of Duke University may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DUKE UNIVERSITY ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DUKE UNIVERSITY BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITSOR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/*
+ * This is a set of routines for allocating large-sized mbuf payload
+ * areas, and is primarily intended for use in receive side mbuf
+ * allocation.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/sockio.h>
+#include <sys/uio.h>
+#include <sys/lock.h>
+#include <sys/kernel.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_map.h>
+#include <vm/vm_param.h>
+#include <vm/vm_pageout.h>
+#include <sys/vmmeter.h>
+#include <vm/vm_page.h>
+#include <vm/vm_object.h>
+#include <vm/vm_kern.h>
+#include <sys/proc.h>
+#include <sys/jumbo.h>
+
+/*
+ * XXX this may be too high or too low.
+ */
+#define JUMBO_MAX_PAGES 3072
+
+struct jumbo_kmap {
+ vm_offset_t kva;
+ SLIST_ENTRY(jumbo_kmap) entries; /* Singly-linked List. */
+};
+
+static SLIST_HEAD(jumbo_kmap_head, jumbo_kmap) jumbo_kmap_free,
+ jumbo_kmap_inuse;
+
+static struct mtx jumbo_mutex;
+MTX_SYSINIT(jumbo_lock, &jumbo_mutex, "jumbo mutex", MTX_DEF);
+
+static struct vm_object *jumbo_vm_object;
+static unsigned long jumbo_vmuiomove_pgs_freed = 0;
+#if 0
+static int jumbo_vm_wakeup_wanted = 0;
+#endif
+vm_offset_t jumbo_basekva;
+
+int
+jumbo_vm_init(void)
+{
+ int i;
+ struct jumbo_kmap *entry;
+
+ mtx_lock(&jumbo_mutex);
+
+ if (jumbo_vm_object != NULL) {
+ mtx_unlock(&jumbo_mutex);
+ return (1);
+ }
+
+ /* allocate our object */
+ jumbo_vm_object = vm_object_allocate_wait(OBJT_DEFAULT, JUMBO_MAX_PAGES,
+ M_NOWAIT);
+
+ if (jumbo_vm_object == NULL) {
+ mtx_unlock(&jumbo_mutex);
+ return (0);
+ }
+
+ SLIST_INIT(&jumbo_kmap_free);
+ SLIST_INIT(&jumbo_kmap_inuse);
+
+ /* grab some kernel virtual address space */
+ jumbo_basekva = kmem_alloc_pageable(kernel_map,
+ PAGE_SIZE * JUMBO_MAX_PAGES);
+ if (jumbo_basekva == 0) {
+ vm_object_deallocate(jumbo_vm_object);
+ jumbo_vm_object = NULL;
+ mtx_unlock(&jumbo_mutex);
+ return 0;
+ }
+ for (i = 0; i < JUMBO_MAX_PAGES; i++) {
+ entry = malloc(sizeof(struct jumbo_kmap), M_TEMP, M_NOWAIT);
+ if (!entry && !i) {
+ mtx_unlock(&jumbo_mutex);
+ panic("jumbo_vm_init: unable to allocated kvas");
+ } else if (!entry) {
+ printf("warning: jumbo_vm_init allocated only %d kva\n",
+ i);
+ mtx_unlock(&jumbo_mutex);
+ return 1;
+ }
+ entry->kva = jumbo_basekva + (vm_offset_t)i * PAGE_SIZE;
+ SLIST_INSERT_HEAD(&jumbo_kmap_free, entry, entries);
+ }
+ mtx_unlock(&jumbo_mutex);
+ return 1;
+}
+
+void
+jumbo_freem(caddr_t addr, void *args)
+{
+ vm_page_t frame;
+
+ frame = PHYS_TO_VM_PAGE(pmap_kextract((vm_offset_t)addr));
+
+ /*
+ * Need giant for looking at the hold count below. Convert this
+ * to the vm mutex once the VM code has been moved out from under
+ * giant.
+ */
+ GIANT_REQUIRED;
+
+ if (frame->hold_count == 0)
+ jumbo_pg_free((vm_offset_t)addr);
+ else
+ printf("jumbo_freem: hold count for %p is %d!!??\n",
+ frame, frame->hold_count);
+}
+
+void
+jumbo_pg_steal(vm_page_t pg)
+{
+ vm_offset_t addr;
+ struct jumbo_kmap *entry;
+
+ addr = ptoa(pg->pindex) + jumbo_basekva;
+
+ if (pg->object != jumbo_vm_object)
+ panic("stealing a non jumbo_vm_object page");
+ vm_page_remove(pg);
+
+ mtx_lock(&jumbo_mutex);
+
+ pmap_qremove(addr,1);
+ entry = SLIST_FIRST(&jumbo_kmap_inuse);
+ entry->kva = addr;
+ SLIST_REMOVE_HEAD(&jumbo_kmap_inuse, entries);
+ SLIST_INSERT_HEAD(&jumbo_kmap_free, entry, entries);
+
+ mtx_unlock(&jumbo_mutex);
+
+#if 0
+ if (jumbo_vm_wakeup_wanted)
+ wakeup(jumbo_vm_object);
+#endif
+}
+
+
+vm_page_t
+jumbo_pg_alloc(void)
+{
+ vm_page_t pg;
+ vm_pindex_t pindex;
+ struct jumbo_kmap *entry;
+
+ pg = NULL;
+ mtx_lock(&jumbo_mutex);
+
+ entry = SLIST_FIRST(&jumbo_kmap_free);
+ if (entry != NULL){
+ pindex = atop(entry->kva - jumbo_basekva);
+ pg = vm_page_alloc(jumbo_vm_object, pindex, VM_ALLOC_INTERRUPT);
+ if (pg != NULL) {
+ SLIST_REMOVE_HEAD(&jumbo_kmap_free, entries);
+ SLIST_INSERT_HEAD(&jumbo_kmap_inuse, entry, entries);
+ pmap_qenter(entry->kva, &pg, 1);
+ }
+ }
+ mtx_unlock(&jumbo_mutex);
+ return(pg);
+}
+
+void
+jumbo_pg_free(vm_offset_t addr)
+{
+ struct jumbo_kmap *entry;
+ vm_offset_t paddr;
+ vm_page_t pg;
+
+ paddr = pmap_kextract((vm_offset_t)addr);
+ pg = PHYS_TO_VM_PAGE(paddr);
+
+ if (pg->object != jumbo_vm_object) {
+ jumbo_vmuiomove_pgs_freed++;
+/* if(vm_page_lookup(jumbo_vm_object, atop(addr - jumbo_basekva)))
+ panic("vm_page_rename didn't");
+ printf("freeing uiomoved pg:\t pindex = %d, padd = 0x%lx\n",
+ atop(addr - jumbo_basekva), paddr);
+*/
+ } else {
+ vm_page_busy(pg); /* vm_page_free wants pages to be busy*/
+ vm_page_free(pg);
+ }
+
+ mtx_lock(&jumbo_mutex);
+
+ pmap_qremove(addr,1);
+ entry = SLIST_FIRST(&jumbo_kmap_inuse);
+ entry->kva = addr;
+ SLIST_REMOVE_HEAD(&jumbo_kmap_inuse, entries);
+ SLIST_INSERT_HEAD(&jumbo_kmap_free, entry, entries);
+
+ mtx_unlock(&jumbo_mutex);
+
+#if 0
+ if (jumbo_vm_wakeup_wanted)
+ wakeup(jumbo_vm_object);
+#endif
+}
OpenPOWER on IntegriCloud