summaryrefslogtreecommitdiffstats
path: root/sys/vm/memguard.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/memguard.c')
-rw-r--r--sys/vm/memguard.c90
1 files changed, 90 insertions, 0 deletions
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).
OpenPOWER on IntegriCloud