summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_malloc.c30
-rw-r--r--sys/sys/malloc.h2
-rw-r--r--sys/vm/memguard.c90
-rw-r--r--sys/vm/memguard.h3
4 files changed, 112 insertions, 13 deletions
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index 4864277..6b2e73d 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -142,12 +142,6 @@ struct {
static uma_zone_t mt_zone;
-#ifdef DEBUG_MEMGUARD
-u_int vm_memguard_divisor;
-SYSCTL_UINT(_vm, OID_AUTO, memguard_divisor, CTLFLAG_RD, &vm_memguard_divisor,
- 0, "(kmem_size/memguard_divisor) == memguard submap size");
-#endif
-
u_int vm_kmem_size;
SYSCTL_UINT(_vm, OID_AUTO, kmem_size, CTLFLAG_RD, &vm_kmem_size, 0,
"Size of kernel memory");
@@ -304,8 +298,7 @@ malloc(unsigned long size, struct malloc_type *mtp, int flags)
("malloc(M_WAITOK) in interrupt context"));
#ifdef DEBUG_MEMGUARD
- /* XXX CHANGEME! */
- if (mtp == M_SUBPROC)
+ if (memguard_cmp(mtp))
return memguard_alloc(size, flags);
#endif
@@ -359,8 +352,7 @@ free(void *addr, struct malloc_type *mtp)
return;
#ifdef DEBUG_MEMGUARD
- /* XXX CHANGEME! */
- if (mtp == M_SUBPROC) {
+ if (memguard_cmp(mtp)) {
memguard_free(addr);
return;
}
@@ -423,8 +415,7 @@ realloc(void *addr, unsigned long size, struct malloc_type *mtp, int flags)
*/
#ifdef DEBUG_MEMGUARD
-/* XXX: CHANGEME! */
-if (mtp == M_SUBPROC) {
+if (memguard_cmp(mtp)) {
slab = NULL;
alloc = size;
} else {
@@ -549,7 +540,7 @@ kmeminit(void *dummy)
* scenarios as they occur. It is only used for debugging.
*/
vm_memguard_divisor = 10;
- TUNABLE_INT_FETCH("vm.memguard_divisor", &vm_memguard_divisor);
+ TUNABLE_INT_FETCH("vm.memguard.divisor", &vm_memguard_divisor);
/* Pick a conservative value if provided value sucks. */
if ((vm_memguard_divisor <= 0) ||
@@ -649,6 +640,19 @@ malloc_uninit(void *data)
uma_zfree(mt_zone, mtip);
}
+struct malloc_type *
+malloc_desc2type(const char *desc)
+{
+ struct malloc_type *mtp;
+
+ mtx_assert(&malloc_mtx, MA_OWNED);
+ for (mtp = kmemstatistics; mtp != NULL; mtp = mtp->ks_next) {
+ if (strcmp(mtp->ks_shortdesc, desc) == 0)
+ return (mtp);
+ }
+ return (NULL);
+}
+
static int
sysctl_kern_malloc(SYSCTL_HANDLER_ARGS)
{
diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h
index f1bdedb..e59b9ac 100644
--- a/sys/sys/malloc.h
+++ b/sys/sys/malloc.h
@@ -189,6 +189,8 @@ void *realloc(void *addr, unsigned long size, struct malloc_type *type,
int flags);
void *reallocf(void *addr, unsigned long size, struct malloc_type *type,
int flags);
+
+struct malloc_type *malloc_desc2type(const char *desc);
#endif /* _KERNEL */
#endif /* !_SYS_MALLOC_H_ */
diff --git a/sys/vm/memguard.c b/sys/vm/memguard.c
index 2140a0b..9a4f98b 100644
--- a/sys/vm/memguard.c
+++ b/sys/vm/memguard.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
+#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -59,6 +60,67 @@ __FBSDID("$FreeBSD$");
*/
#define MAX_PAGES_PER_ITEM 64
+SYSCTL_NODE(_vm, OID_AUTO, memguard, CTLFLAG_RW, NULL, "MemGuard data");
+/*
+ * The vm_memguard_divisor variable controls how much of kmem_map should be
+ * reserved for MemGuard.
+ */
+u_int vm_memguard_divisor;
+SYSCTL_UINT(_vm_memguard, OID_AUTO, divisor, CTLFLAG_RD, &vm_memguard_divisor,
+ 0, "(kmem_size/memguard_divisor) == memguard submap size");
+
+/*
+ * Short description (ks_shortdesc) of memory type to monitor.
+ */
+static char vm_memguard_desc[128] = "";
+static struct malloc_type *vm_memguard_mtype = NULL;
+TUNABLE_STR("vm.memguard.desc", vm_memguard_desc, sizeof(vm_memguard_desc));
+static int
+memguard_sysctl_desc(SYSCTL_HANDLER_ARGS)
+{
+ struct malloc_type_internal *mtip;
+ struct malloc_type_stats *mtsp;
+ struct malloc_type *mtp;
+ char desc[128];
+ long bytes;
+ int error, i;
+
+ strlcpy(desc, vm_memguard_desc, sizeof(desc));
+ error = sysctl_handle_string(oidp, desc, sizeof(desc), req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ /*
+ * We can change memory type when no memory has been allocated for it
+ * or when there is no such memory type yet (ie. it will be loaded with
+ * kernel module).
+ */
+ bytes = 0;
+ mtx_lock(&malloc_mtx);
+ mtp = malloc_desc2type(desc);
+ if (mtp != NULL) {
+ mtip = mtp->ks_handle;
+ for (i = 0; i < MAXCPU; i++) {
+ mtsp = &mtip->mti_stats[i];
+ bytes += mtsp->mts_memalloced;
+ bytes -= mtsp->mts_memfreed;
+ }
+ }
+ if (bytes > 0)
+ error = EBUSY;
+ else {
+ /*
+ * If mtp is NULL, it will be initialized in memguard_cmp().
+ */
+ vm_memguard_mtype = mtp;
+ strlcpy(vm_memguard_desc, desc, sizeof(vm_memguard_desc));
+ }
+ mtx_unlock(&malloc_mtx);
+ return (error);
+}
+SYSCTL_PROC(_vm_memguard, OID_AUTO, desc, CTLTYPE_STRING | CTLFLAG_RW, 0, 0,
+ memguard_sysctl_desc, "A", "Short description of memory type to monitor");
+
/*
* Global MemGuard data.
*/
@@ -239,6 +301,34 @@ memguard_free(void *addr)
MEMGUARD_CRIT_SECTION_EXIT;
}
+int
+memguard_cmp(struct malloc_type *mtp)
+{
+
+#if 1
+ /*
+ * The safest way of comparsion is to always compare short description
+ * string of memory type, but it is also the slowest way.
+ */
+ return (strcmp(mtp->ks_shortdesc, vm_memguard_desc) == 0);
+#else
+ /*
+ * If we compare pointers, there are two possible problems:
+ * 1. Memory type was unloaded and new memory type was allocated at the
+ * same address.
+ * 2. Memory type was unloaded and loaded again, but allocated at a
+ * different address.
+ */
+ if (vm_memguard_mtype != NULL)
+ return (mtp == vm_memguard_mtype);
+ if (strcmp(mtp->ks_shortdesc, vm_memguard_desc) == 0) {
+ vm_memguard_mtype = mtp;
+ return (1);
+ }
+ return (0);
+#endif
+}
+
/*
* Guard a page containing specified object (make it read-only so that
* future writes to it fail).
diff --git a/sys/vm/memguard.h b/sys/vm/memguard.h
index 10ca96d..34d79cf 100644
--- a/sys/vm/memguard.h
+++ b/sys/vm/memguard.h
@@ -26,6 +26,9 @@
* $FreeBSD$
*/
+extern u_int vm_memguard_divisor;
+
void memguard_init(vm_map_t parent_map, unsigned long size);
void *memguard_alloc(unsigned long size, int flags);
void memguard_free(void *addr);
+int memguard_cmp(struct malloc_type *mtp);
OpenPOWER on IntegriCloud