summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/include/vmparam.h2
-rw-r--r--sys/arm/arm/pmap.c2
-rw-r--r--sys/arm/include/vmparam.h3
-rw-r--r--sys/dev/md/md.c10
-rw-r--r--sys/dev/null/null.c19
-rw-r--r--sys/i386/include/vmparam.h2
-rw-r--r--sys/ia64/include/vmparam.h2
-rw-r--r--sys/mips/include/vmparam.h2
-rw-r--r--sys/powerpc/include/vmparam.h2
-rw-r--r--sys/sparc64/include/vmparam.h7
-rw-r--r--sys/sun4v/include/vmparam.h2
-rw-r--r--sys/sys/queue.h13
-rw-r--r--sys/sys/systm.h2
-rw-r--r--sys/vm/vm_kern.c31
14 files changed, 81 insertions, 18 deletions
diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h
index 38a6214..0c65602 100644
--- a/sys/amd64/include/vmparam.h
+++ b/sys/amd64/include/vmparam.h
@@ -212,4 +212,6 @@
#define VM_INITIAL_PAGEIN 16
#endif
+#define ZERO_REGION_SIZE (2 * 1024 * 1024) /* 2MB */
+
#endif /* _MACHINE_VMPARAM_H_ */
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index 16487b0..cecf363 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -3646,7 +3646,7 @@ pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired)
pte = *ptep;
pg = PHYS_TO_VM_PAGE(l2pte_pa(pte));
if (pg)
- pmap_modify_pv(pg, pmap, va, PVF_WIRED, wired);
+ pmap_modify_pv(pg, pmap, va, PVF_WIRED, wired ? PVF_WIRED : 0);
vm_page_unlock_queues();
PMAP_UNLOCK(pmap);
}
diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
index c608daa..dd1ba1c 100644
--- a/sys/arm/include/vmparam.h
+++ b/sys/arm/include/vmparam.h
@@ -150,4 +150,7 @@
#ifdef ARM_USE_SMALL_ALLOC
#define UMA_MD_SMALL_ALLOC
#endif /* ARM_USE_SMALL_ALLOC */
+
+#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */
+
#endif /* _MACHINE_VMPARAM_H_ */
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index 79bf19c..c488728 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -89,6 +89,8 @@
#include <vm/swap_pager.h>
#include <vm/uma.h>
+#include <machine/vmparam.h>
+
#define MD_MODVER 1
#define MD_SHUTDOWN 0x10000 /* Tell worker thread to terminate. */
@@ -205,9 +207,6 @@ struct md_s {
vm_object_t object;
};
-/* Used for BIO_DELETE on MD_VNODE */
-static u_char zero[PAGE_SIZE];
-
static struct indir *
new_indir(u_int shift)
{
@@ -560,7 +559,8 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
* that the two cases end up having very little in common.
*/
if (bp->bio_cmd == BIO_DELETE) {
- zerosize = sizeof(zero) - (sizeof(zero) % sc->sectorsize);
+ zerosize = ZERO_REGION_SIZE -
+ (ZERO_REGION_SIZE % sc->sectorsize);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = (vm_ooffset_t)bp->bio_offset;
@@ -573,7 +573,7 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
error = 0;
while (auio.uio_offset < end) {
- aiov.iov_base = zero;
+ aiov.iov_base = __DECONST(void *, zero_region);
aiov.iov_len = end - auio.uio_offset;
if (aiov.iov_len > zerosize)
aiov.iov_len = zerosize;
diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c
index 3005c19..b053d5d 100644
--- a/sys/dev/null/null.c
+++ b/sys/dev/null/null.c
@@ -39,7 +39,9 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/disk.h>
#include <sys/bus.h>
+
#include <machine/bus.h>
+#include <machine/vmparam.h>
/* For use with destroy_dev(9). */
static struct cdev *null_dev;
@@ -65,8 +67,6 @@ static struct cdevsw zero_cdevsw = {
.d_flags = D_MMAP_ANON,
};
-static void *zbuf;
-
/* ARGSUSED */
static int
null_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
@@ -95,10 +95,19 @@ null_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data __unused,
static int
zero_read(struct cdev *dev __unused, struct uio *uio, int flags __unused)
{
+ void *zbuf;
+ ssize_t len;
int error = 0;
- while (uio->uio_resid > 0 && error == 0)
- error = uiomove(zbuf, MIN(uio->uio_resid, PAGE_SIZE), uio);
+ KASSERT(uio->uio_rw == UIO_READ,
+ ("Can't be in %s for write", __func__));
+ zbuf = __DECONST(void *, zero_region);
+ while (uio->uio_resid > 0 && error == 0) {
+ len = uio->uio_resid;
+ if (len > ZERO_REGION_SIZE)
+ len = ZERO_REGION_SIZE;
+ error = uiomove(zbuf, len, uio);
+ }
return (error);
}
@@ -111,7 +120,6 @@ null_modevent(module_t mod __unused, int type, void *data __unused)
case MOD_LOAD:
if (bootverbose)
printf("null: <null device, zero device>\n");
- zbuf = (void *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK | M_ZERO);
null_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &null_cdevsw, 0,
NULL, UID_ROOT, GID_WHEEL, 0666, "null");
zero_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &zero_cdevsw, 0,
@@ -121,7 +129,6 @@ null_modevent(module_t mod __unused, int type, void *data __unused)
case MOD_UNLOAD:
destroy_dev(null_dev);
destroy_dev(zero_dev);
- free(zbuf, M_TEMP);
break;
case MOD_SHUTDOWN:
diff --git a/sys/i386/include/vmparam.h b/sys/i386/include/vmparam.h
index 9eaa3f7..8fe9b2b 100644
--- a/sys/i386/include/vmparam.h
+++ b/sys/i386/include/vmparam.h
@@ -198,4 +198,6 @@
#define VM_INITIAL_PAGEIN 16
#endif
+#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */
+
#endif /* _MACHINE_VMPARAM_H_ */
diff --git a/sys/ia64/include/vmparam.h b/sys/ia64/include/vmparam.h
index e93ca1b..16c5e7d 100644
--- a/sys/ia64/include/vmparam.h
+++ b/sys/ia64/include/vmparam.h
@@ -215,4 +215,6 @@
#define VM_INITIAL_PAGEIN 16
#endif
+#define ZERO_REGION_SIZE (2 * 1024 * 1024) /* 2MB */
+
#endif /* !_MACHINE_VMPARAM_H_ */
diff --git a/sys/mips/include/vmparam.h b/sys/mips/include/vmparam.h
index ef01601..4a702f5 100644
--- a/sys/mips/include/vmparam.h
+++ b/sys/mips/include/vmparam.h
@@ -187,4 +187,6 @@
*/
#define VM_NFREEORDER 9
+#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */
+
#endif /* !_MACHINE_VMPARAM_H_ */
diff --git a/sys/powerpc/include/vmparam.h b/sys/powerpc/include/vmparam.h
index d72e0ea..cec455f 100644
--- a/sys/powerpc/include/vmparam.h
+++ b/sys/powerpc/include/vmparam.h
@@ -198,4 +198,6 @@ struct pmap_physseg {
#endif
#endif
+#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */
+
#endif /* _MACHINE_VMPARAM_H_ */
diff --git a/sys/sparc64/include/vmparam.h b/sys/sparc64/include/vmparam.h
index 0638d0d..1b9e537 100644
--- a/sys/sparc64/include/vmparam.h
+++ b/sys/sparc64/include/vmparam.h
@@ -240,4 +240,11 @@
extern vm_offset_t vm_max_kernel_address;
+/*
+ * Older sparc64 machines have a virtually indexed L1 data cache of 16KB.
+ * Consequently, mapping the same physical page multiple times may have
+ * caching disabled.
+ */
+#define ZERO_REGION_SIZE PAGE_SIZE
+
#endif /* !_MACHINE_VMPARAM_H_ */
diff --git a/sys/sun4v/include/vmparam.h b/sys/sun4v/include/vmparam.h
index 65c7f78..5195f1d 100644
--- a/sys/sun4v/include/vmparam.h
+++ b/sys/sun4v/include/vmparam.h
@@ -223,4 +223,6 @@
#define UMA_MD_SMALL_ALLOC
extern vm_offset_t vm_max_kernel_address;
+#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */
+
#endif /* !_MACHINE_VMPARAM_H_ */
diff --git a/sys/sys/queue.h b/sys/sys/queue.h
index f0bae8d..274e636 100644
--- a/sys/sys/queue.h
+++ b/sys/sys/queue.h
@@ -99,6 +99,7 @@
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
* _REMOVE + + + +
+ * _SWAP + + + +
*
*/
#ifdef QUEUE_MACRO_DEBUG
@@ -307,18 +308,18 @@ struct { \
TRASHIT(*oldnext); \
} while (0)
-#define STAILQ_REMOVE_HEAD(head, field) do { \
- if ((STAILQ_FIRST((head)) = \
- STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
#define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 80fb0a9..e563a5a 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -125,6 +125,8 @@ extern char static_hints[]; /* by config for now */
extern char **kenvp;
+extern const void *zero_region; /* address space maps to a zeroed page */
+
/*
* General function declarations.
*/
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index 0360af7..23884af 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -91,6 +91,9 @@ vm_map_t exec_map=0;
vm_map_t pipe_map;
vm_map_t buffer_map=0;
+const void *zero_region;
+CTASSERT((ZERO_REGION_SIZE & PAGE_MASK) == 0);
+
/*
* kmem_alloc_nofault:
*
@@ -527,6 +530,32 @@ kmem_free_wakeup(map, addr, size)
vm_map_unlock(map);
}
+static void
+kmem_init_zero_region(void)
+{
+ vm_offset_t addr, i;
+ vm_page_t m;
+ int error;
+
+ /*
+ * Map a single physical page of zeros to a larger virtual range.
+ * This requires less looping in places that want large amounts of
+ * zeros, while not using much more physical resources.
+ */
+ addr = kmem_alloc_nofault(kernel_map, ZERO_REGION_SIZE);
+ m = vm_page_alloc(NULL, OFF_TO_IDX(addr - VM_MIN_KERNEL_ADDRESS),
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+ if ((m->flags & PG_ZERO) == 0)
+ pmap_zero_page(m);
+ for (i = 0; i < ZERO_REGION_SIZE; i += PAGE_SIZE)
+ pmap_qenter(addr + i, &m, 1);
+ error = vm_map_protect(kernel_map, addr, addr + ZERO_REGION_SIZE,
+ VM_PROT_READ, TRUE);
+ KASSERT(error == 0, ("error=%d", error));
+
+ zero_region = (const void *)addr;
+}
+
/*
* kmem_init:
*
@@ -555,6 +584,8 @@ kmem_init(start, end)
start, VM_PROT_ALL, VM_PROT_ALL, MAP_NOFAULT);
/* ... and ending with the completion of the above `insert' */
vm_map_unlock(m);
+
+ kmem_init_zero_region();
}
#ifdef DIAGNOSTIC
OpenPOWER on IntegriCloud