aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@xensource.com>2007-10-16 14:51:30 -0400
committerJeremy Fitzhardinge <jeremy@goop.org>2007-10-16 14:51:30 -0400
commit91e0c5f3dad47838cb2ecc1865ce789a0b7182b1 (patch)
tree8c72d3f7bd574088fc457f0ce2117d6d986dac2c
parentf0d733942750c1ee6358c3a4a1a5d7ba73b7122f (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>
-rw-r--r--arch/x86/xen/multicalls.c29
-rw-r--r--arch/x86/xen/multicalls.h3
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 @@
32struct mc_buffer { 32struct 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
38static DEFINE_PER_CPU(struct mc_buffer, mc_buffer); 42static 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
102void 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 */
46void xen_mc_callback(void (*fn)(void *), void *data);
47
45#endif /* _XEN_MULTICALLS_H */ 48#endif /* _XEN_MULTICALLS_H */