aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2013-09-11 17:24:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:58:52 -0400
commitaf96397de8600232effbff43dc8b4ca20ddc02b1 (patch)
treed236fe3b4d37d5439ee41497a0d179a0b7614883 /kernel
parentc802d64a356b5cf349121ac4c5e005f037ce548d (diff)
kprobes: allow to specify custom allocator for insn caches
The current two insn slot caches both use module_alloc/module_free to allocate and free insn slot cache pages. For s390 this is not sufficient since there is the need to allocate insn slots that are either within the vmalloc module area or within dma memory. Therefore add a mechanism which allows to specify an own allocator for an own insn slot cache. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kprobes.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 9e4912dc5559..a0d367a49122 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -112,6 +112,7 @@ static struct kprobe_blackpoint kprobe_blacklist[] = {
112struct kprobe_insn_page { 112struct kprobe_insn_page {
113 struct list_head list; 113 struct list_head list;
114 kprobe_opcode_t *insns; /* Page of instruction slots */ 114 kprobe_opcode_t *insns; /* Page of instruction slots */
115 struct kprobe_insn_cache *cache;
115 int nused; 116 int nused;
116 int ngarbage; 117 int ngarbage;
117 char slot_used[]; 118 char slot_used[];
@@ -132,8 +133,20 @@ enum kprobe_slot_state {
132 SLOT_USED = 2, 133 SLOT_USED = 2,
133}; 134};
134 135
136static void *alloc_insn_page(void)
137{
138 return module_alloc(PAGE_SIZE);
139}
140
141static void free_insn_page(void *page)
142{
143 module_free(NULL, page);
144}
145
135struct kprobe_insn_cache kprobe_insn_slots = { 146struct kprobe_insn_cache kprobe_insn_slots = {
136 .mutex = __MUTEX_INITIALIZER(kprobe_insn_slots.mutex), 147 .mutex = __MUTEX_INITIALIZER(kprobe_insn_slots.mutex),
148 .alloc = alloc_insn_page,
149 .free = free_insn_page,
137 .pages = LIST_HEAD_INIT(kprobe_insn_slots.pages), 150 .pages = LIST_HEAD_INIT(kprobe_insn_slots.pages),
138 .insn_size = MAX_INSN_SIZE, 151 .insn_size = MAX_INSN_SIZE,
139 .nr_garbage = 0, 152 .nr_garbage = 0,
@@ -182,7 +195,7 @@ kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c)
182 * kernel image and loaded module images reside. This is required 195 * kernel image and loaded module images reside. This is required
183 * so x86_64 can correctly handle the %rip-relative fixups. 196 * so x86_64 can correctly handle the %rip-relative fixups.
184 */ 197 */
185 kip->insns = module_alloc(PAGE_SIZE); 198 kip->insns = c->alloc();
186 if (!kip->insns) { 199 if (!kip->insns) {
187 kfree(kip); 200 kfree(kip);
188 goto out; 201 goto out;
@@ -192,6 +205,7 @@ kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c)
192 kip->slot_used[0] = SLOT_USED; 205 kip->slot_used[0] = SLOT_USED;
193 kip->nused = 1; 206 kip->nused = 1;
194 kip->ngarbage = 0; 207 kip->ngarbage = 0;
208 kip->cache = c;
195 list_add(&kip->list, &c->pages); 209 list_add(&kip->list, &c->pages);
196 slot = kip->insns; 210 slot = kip->insns;
197out: 211out:
@@ -213,7 +227,7 @@ static int __kprobes collect_one_slot(struct kprobe_insn_page *kip, int idx)
213 */ 227 */
214 if (!list_is_singular(&kip->list)) { 228 if (!list_is_singular(&kip->list)) {
215 list_del(&kip->list); 229 list_del(&kip->list);
216 module_free(NULL, kip->insns); 230 kip->cache->free(kip->insns);
217 kfree(kip); 231 kfree(kip);
218 } 232 }
219 return 1; 233 return 1;
@@ -274,6 +288,8 @@ out:
274/* For optimized_kprobe buffer */ 288/* For optimized_kprobe buffer */
275struct kprobe_insn_cache kprobe_optinsn_slots = { 289struct kprobe_insn_cache kprobe_optinsn_slots = {
276 .mutex = __MUTEX_INITIALIZER(kprobe_optinsn_slots.mutex), 290 .mutex = __MUTEX_INITIALIZER(kprobe_optinsn_slots.mutex),
291 .alloc = alloc_insn_page,
292 .free = free_insn_page,
277 .pages = LIST_HEAD_INIT(kprobe_optinsn_slots.pages), 293 .pages = LIST_HEAD_INIT(kprobe_optinsn_slots.pages),
278 /* .insn_size is initialized later */ 294 /* .insn_size is initialized later */
279 .nr_garbage = 0, 295 .nr_garbage = 0,