diff options
author | Jeremy Fitzhardinge <jeremy@xensource.com> | 2007-10-16 14:51:30 -0400 |
---|---|---|
committer | Jeremy Fitzhardinge <jeremy@goop.org> | 2007-10-16 14:51:30 -0400 |
commit | 91e0c5f3dad47838cb2ecc1865ce789a0b7182b1 (patch) | |
tree | 8c72d3f7bd574088fc457f0ce2117d6d986dac2c /arch/x86 | |
parent | f0d733942750c1ee6358c3a4a1a5d7ba73b7122f (diff) |
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>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/xen/multicalls.c | 29 | ||||
-rw-r--r-- | arch/x86/xen/multicalls.h | 3 |
2 files changed, 29 insertions, 3 deletions
diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c index c837e8e463db..ce9c4b41f02d 100644 --- a/arch/x86/xen/multicalls.c +++ b/arch/x86/xen/multicalls.c | |||
@@ -32,7 +32,11 @@ | |||
32 | struct mc_buffer { | 32 | struct mc_buffer { |
33 | struct multicall_entry entries[MC_BATCH]; | 33 | struct multicall_entry entries[MC_BATCH]; |
34 | u64 args[MC_ARGS]; | 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 | static DEFINE_PER_CPU(struct mc_buffer, mc_buffer); | 42 | static DEFINE_PER_CPU(struct mc_buffer, mc_buffer); |
@@ -43,6 +47,7 @@ void xen_mc_flush(void) | |||
43 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); | 47 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); |
44 | int ret = 0; | 48 | int ret = 0; |
45 | unsigned long flags; | 49 | unsigned long flags; |
50 | int i; | ||
46 | 51 | ||
47 | BUG_ON(preemptible()); | 52 | BUG_ON(preemptible()); |
48 | 53 | ||
@@ -51,8 +56,6 @@ void xen_mc_flush(void) | |||
51 | local_irq_save(flags); | 56 | local_irq_save(flags); |
52 | 57 | ||
53 | if (b->mcidx) { | 58 | if (b->mcidx) { |
54 | int i; | ||
55 | |||
56 | if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0) | 59 | if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0) |
57 | BUG(); | 60 | BUG(); |
58 | for (i = 0; i < b->mcidx; i++) | 61 | for (i = 0; i < b->mcidx; i++) |
@@ -65,6 +68,13 @@ void xen_mc_flush(void) | |||
65 | 68 | ||
66 | local_irq_restore(flags); | 69 | local_irq_restore(flags); |
67 | 70 | ||
71 | for(i = 0; i < b->cbidx; i++) { | ||
72 | struct callback *cb = &b->callbacks[i]; | ||
73 | |||
74 | (*cb->fn)(cb->data); | ||
75 | } | ||
76 | b->cbidx = 0; | ||
77 | |||
68 | BUG_ON(ret); | 78 | BUG_ON(ret); |
69 | } | 79 | } |
70 | 80 | ||
@@ -88,3 +98,16 @@ struct multicall_space __xen_mc_entry(size_t args) | |||
88 | 98 | ||
89 | return ret; | 99 | return ret; |
90 | } | 100 | } |
101 | |||
102 | void xen_mc_callback(void (*fn)(void *), void *data) | ||
103 | { | ||
104 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); | ||
105 | struct callback *cb; | ||
106 | |||
107 | if (b->cbidx == MC_BATCH) | ||
108 | xen_mc_flush(); | ||
109 | |||
110 | cb = &b->callbacks[b->cbidx++]; | ||
111 | cb->fn = fn; | ||
112 | cb->data = data; | ||
113 | } | ||
diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h index 5d96a5fa210c..8bae996d99a3 100644 --- a/arch/x86/xen/multicalls.h +++ b/arch/x86/xen/multicalls.h | |||
@@ -42,4 +42,7 @@ static inline void xen_mc_issue(unsigned mode) | |||
42 | local_irq_restore(x86_read_percpu(xen_mc_irq_flags)); | 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 | #endif /* _XEN_MULTICALLS_H */ | 48 | #endif /* _XEN_MULTICALLS_H */ |