[PATCH 6/6] VM: Annotate vmalloc

From: Steve VanDeBogart
Date: Fri Aug 29 2008 - 19:18:27 EST


Valgrind annotations for vmalloc: Valgrind doesn't understand memory
that is mapped to more than one address. Approximate validness by
assuming that the physical mapping won't be used while it is vmalloc'd
and copy the valid bits from the physical page when the fault handler
maps it in.

Signed-off-by: Steve VanDeBogart <vandebo-lkml@xxxxxxxxxxx>
---

Index: linux-2.6.27-rc5/arch/um/kernel/physmem.c
===================================================================
--- linux-2.6.27-rc5.orig/arch/um/kernel/physmem.c 2008-08-29 14:17:31.000000000 -0700
+++ linux-2.6.27-rc5/arch/um/kernel/physmem.c 2008-08-29 14:24:46.000000000 -0700
@@ -6,6 +6,7 @@
#include "linux/bootmem.h"
#include "linux/mm.h"
#include "linux/pfn.h"
+#include "linux/memcheck.h"
#include "asm/page.h"
#include "as-layout.h"
#include "init.h"
@@ -71,6 +72,26 @@
panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
"err = %d\n", virt, fd, offset, len, r, w, x, err);
}
+#ifdef CONFIG_VALGRIND_SUPPORT
+ if (virt >= VMALLOC_START && virt < VMALLOC_END) {
+ /* As far as I know, the backing pages were just page alloc'd,
+ * so they are addressable, but may be either valid or invalid
+ * (depending on gfp_mask). The virtual address may be part of
+ * a vmalloc region, or a guard page, so inaddressability is ok.
+ */
+#define CHUNK_SIZE (PAGE_SIZE/8)
+ char vbits[CHUNK_SIZE];
+ int i;
+ if (len % (CHUNK_SIZE) != 0)
+ panic("Expected len to be a multiple of page size");
+ for (i = 0; i < len; i += CHUNK_SIZE) {
+ if (VALGRIND_GET_VBITS(__va(phys + i), vbits,
+ CHUNK_SIZE) > 1)
+ panic("Expected addressable source memory");
+ VALGRIND_SET_VBITS(virt + i, vbits, CHUNK_SIZE);
+ }
+ }
+#endif
}

extern int __syscall_stub_start;
Index: linux-2.6.27-rc5/mm/vmalloc.c
===================================================================
--- linux-2.6.27-rc5.orig/mm/vmalloc.c 2008-08-29 14:17:38.000000000 -0700
+++ linux-2.6.27-rc5/mm/vmalloc.c 2008-08-29 14:24:46.000000000 -0700
@@ -18,6 +18,7 @@
#include <linux/debugobjects.h>
#include <linux/vmalloc.h>
#include <linux/kallsyms.h>
+#include <linux/memcheck.h>

#include <asm/uaccess.h>
#include <asm/tlbflush.h>
@@ -428,6 +429,8 @@
void vfree(const void *addr)
{
BUG_ON(in_interrupt());
+ if (addr)
+ VALGRIND_FREELIKE_BLOCK(addr, 0);
__vunmap(addr, 1);
}
EXPORT_SYMBOL(vfree);
@@ -555,6 +558,7 @@
int node, void *caller)
{
struct vm_struct *area;
+ void *ret;

size = PAGE_ALIGN(size);
if (!size || (size >> PAGE_SHIFT) > num_physpages)
@@ -566,7 +570,16 @@
if (!area)
return NULL;

- return __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+ VALGRIND_MAKE_MEM_NOACCESS(area->addr, area->size);
+ VALGRIND_MALLOCLIKE_BLOCK(area->addr, size, 0, 0);
+ /* This could be improved by also clearing the addessability bits of
+ * the rounded up region of the last page */
+
+ ret = __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+ if (!ret)
+ VALGRIND_FREELIKE_BLOCK(area->addr, 0);
+
+ return ret;
}

void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/