Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen: add batch completion callbacks

This adds a mechanism to register a callback function to be called once
a batch of hypercalls has been issued. This is typically used to unlock
things which must remain locked until the hypercall has taken place.

[ Stable folks: pre-req for 2.6.23 bugfix "xen: deal with stale cr3
values when unpinning pagetables" ]

Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
Cc: Stable Kernel <stable@kernel.org>

authored by

Jeremy Fitzhardinge and committed by
Jeremy Fitzhardinge
91e0c5f3 f0d73394

+29 -3
+26 -3
arch/x86/xen/multicalls.c
··· 32 32 struct mc_buffer { 33 33 struct multicall_entry entries[MC_BATCH]; 34 34 u64 args[MC_ARGS]; 35 - unsigned mcidx, argidx; 35 + struct callback { 36 + void (*fn)(void *); 37 + void *data; 38 + } callbacks[MC_BATCH]; 39 + unsigned mcidx, argidx, cbidx; 36 40 }; 37 41 38 42 static DEFINE_PER_CPU(struct mc_buffer, mc_buffer); ··· 47 43 struct mc_buffer *b = &__get_cpu_var(mc_buffer); 48 44 int ret = 0; 49 45 unsigned long flags; 46 + int i; 50 47 51 48 BUG_ON(preemptible()); 52 49 ··· 56 51 local_irq_save(flags); 57 52 58 53 if (b->mcidx) { 59 - int i; 60 - 61 54 if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0) 62 55 BUG(); 63 56 for (i = 0; i < b->mcidx; i++) ··· 67 64 BUG_ON(b->argidx != 0); 68 65 69 66 local_irq_restore(flags); 67 + 68 + for(i = 0; i < b->cbidx; i++) { 69 + struct callback *cb = &b->callbacks[i]; 70 + 71 + (*cb->fn)(cb->data); 72 + } 73 + b->cbidx = 0; 70 74 71 75 BUG_ON(ret); 72 76 } ··· 97 87 b->argidx += argspace; 98 88 99 89 return ret; 90 + } 91 + 92 + void xen_mc_callback(void (*fn)(void *), void *data) 93 + { 94 + struct mc_buffer *b = &__get_cpu_var(mc_buffer); 95 + struct callback *cb; 96 + 97 + if (b->cbidx == MC_BATCH) 98 + xen_mc_flush(); 99 + 100 + cb = &b->callbacks[b->cbidx++]; 101 + cb->fn = fn; 102 + cb->data = data; 100 103 }
+3
arch/x86/xen/multicalls.h
··· 42 42 local_irq_restore(x86_read_percpu(xen_mc_irq_flags)); 43 43 } 44 44 45 + /* Set up a callback to be called when the current batch is flushed */ 46 + void xen_mc_callback(void (*fn)(void *), void *data); 47 + 45 48 #endif /* _XEN_MULTICALLS_H */