1 #include <linux/kmemcheck.h>
2 #include <linux/export.h>
6 #include <asm/pgtable.h>
12 * Return the shadow address for the given address. Returns NULL if the
13 * address is not tracked.
15 * We need to be extremely careful not to follow any invalid pointers,
16 * because this function can be called for *any* possible address.
18 void *kmemcheck_shadow_lookup(unsigned long address
)
23 if (!virt_addr_valid(address
))
26 pte
= kmemcheck_pte_lookup(address
);
30 page
= virt_to_page(address
);
33 return page
->shadow
+ (address
& (PAGE_SIZE
- 1));
36 static void mark_shadow(void *address
, unsigned int n
,
37 enum kmemcheck_shadow status
)
39 unsigned long addr
= (unsigned long) address
;
40 unsigned long last_addr
= addr
+ n
- 1;
41 unsigned long page
= addr
& PAGE_MASK
;
42 unsigned long last_page
= last_addr
& PAGE_MASK
;
46 /* If the memory range crosses a page boundary, stop there. */
47 if (page
== last_page
)
50 first_n
= page
+ PAGE_SIZE
- addr
;
52 shadow
= kmemcheck_shadow_lookup(addr
);
54 memset(shadow
, status
, first_n
);
59 /* Do full-page memset()s. */
60 while (n
>= PAGE_SIZE
) {
61 shadow
= kmemcheck_shadow_lookup(addr
);
63 memset(shadow
, status
, PAGE_SIZE
);
69 /* Do the remaining page, if any. */
71 shadow
= kmemcheck_shadow_lookup(addr
);
73 memset(shadow
, status
, n
);
77 void kmemcheck_mark_unallocated(void *address
, unsigned int n
)
79 mark_shadow(address
, n
, KMEMCHECK_SHADOW_UNALLOCATED
);
82 void kmemcheck_mark_uninitialized(void *address
, unsigned int n
)
84 mark_shadow(address
, n
, KMEMCHECK_SHADOW_UNINITIALIZED
);
88 * Fill the shadow memory of the given address such that the memory at that
89 * address is marked as being initialized.
91 void kmemcheck_mark_initialized(void *address
, unsigned int n
)
93 mark_shadow(address
, n
, KMEMCHECK_SHADOW_INITIALIZED
);
95 EXPORT_SYMBOL_GPL(kmemcheck_mark_initialized
);
97 void kmemcheck_mark_freed(void *address
, unsigned int n
)
99 mark_shadow(address
, n
, KMEMCHECK_SHADOW_FREED
);
102 void kmemcheck_mark_unallocated_pages(struct page
*p
, unsigned int n
)
106 for (i
= 0; i
< n
; ++i
)
107 kmemcheck_mark_unallocated(page_address(&p
[i
]), PAGE_SIZE
);
110 void kmemcheck_mark_uninitialized_pages(struct page
*p
, unsigned int n
)
114 for (i
= 0; i
< n
; ++i
)
115 kmemcheck_mark_uninitialized(page_address(&p
[i
]), PAGE_SIZE
);
118 void kmemcheck_mark_initialized_pages(struct page
*p
, unsigned int n
)
122 for (i
= 0; i
< n
; ++i
)
123 kmemcheck_mark_initialized(page_address(&p
[i
]), PAGE_SIZE
);
126 enum kmemcheck_shadow
kmemcheck_shadow_test(void *shadow
, unsigned int size
)
128 #ifdef CONFIG_KMEMCHECK_PARTIAL_OK
135 * Make sure _some_ bytes are initialized. Gcc frequently generates
136 * code to access neighboring bytes.
138 for (i
= 0; i
< size
; ++i
) {
139 if (x
[i
] == KMEMCHECK_SHADOW_INITIALIZED
)
145 return kmemcheck_shadow_test_all(shadow
, size
);
149 enum kmemcheck_shadow
kmemcheck_shadow_test_all(void *shadow
, unsigned int size
)
156 /* All bytes must be initialized. */
157 for (i
= 0; i
< size
; ++i
) {
158 if (x
[i
] != KMEMCHECK_SHADOW_INITIALIZED
)
165 void kmemcheck_shadow_set(void *shadow
, unsigned int size
)
171 for (i
= 0; i
< size
; ++i
)
172 x
[i
] = KMEMCHECK_SHADOW_INITIALIZED
;