direct-io.hg

view unmodified_drivers/linux-2.6/platform-pci/evtchn.c @ 14379:460dac5742cf

Implement VM_metrics Xen-API class.

Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Wed Mar 14 20:41:56 2007 +0000 (2007-03-14)
parents e47738923a05
children 548e61fbdc1a
line source
1 /******************************************************************************
2 * evtchn.c
3 *
4 * A simplified event channel for para-drivers in unmodified linux
5 *
6 * Copyright (c) 2002-2005, K A Fraser
7 * Copyright (c) 2005, Intel Corporation <xiaofeng.ling@intel.com>
8 *
9 * This file may be distributed separately from the Linux kernel, or
10 * incorporated into other software packages, subject to the following license:
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this source file (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use, copy, modify,
15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16 * and to permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <xen/evtchn.h>
34 #include <xen/interface/hvm/ioreq.h>
35 #include <xen/features.h>
36 #include "platform-pci.h"
38 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
39 #include <xen/platform-compat.h>
40 #endif
42 void *shared_info_area;
44 #define MAX_EVTCHN 256
45 static struct {
46 irqreturn_t(*handler) (int, void *, struct pt_regs *);
47 void *dev_id;
48 int close; /* close on unbind_from_irqhandler()? */
49 } evtchns[MAX_EVTCHN];
51 int irq_to_evtchn_port(int irq)
52 {
53 return irq;
54 }
55 EXPORT_SYMBOL(irq_to_evtchn_port);
57 void mask_evtchn(int port)
58 {
59 shared_info_t *s = shared_info_area;
60 synch_set_bit(port, &s->evtchn_mask[0]);
61 }
62 EXPORT_SYMBOL(mask_evtchn);
64 void unmask_evtchn(int port)
65 {
66 unsigned int cpu;
67 shared_info_t *s = shared_info_area;
68 vcpu_info_t *vcpu_info;
70 preempt_disable();
71 cpu = smp_processor_id();
72 vcpu_info = &s->vcpu_info[cpu];
74 /* Slow path (hypercall) if this is a non-local port. We only
75 ever bind event channels to vcpu 0 in HVM guests. */
76 if (unlikely(cpu != 0)) {
77 evtchn_unmask_t op = { .port = port };
78 (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask,
79 &op);
80 preempt_enable();
81 return;
82 }
84 synch_clear_bit(port, &s->evtchn_mask[0]);
86 /*
87 * The following is basically the equivalent of
88 * 'hw_resend_irq'. Just like a real IO-APIC we 'lose the
89 * interrupt edge' if the channel is masked.
90 */
91 if (synch_test_bit(port, &s->evtchn_pending[0]) &&
92 !synch_test_and_set_bit(port / BITS_PER_LONG,
93 &vcpu_info->evtchn_pending_sel)) {
94 vcpu_info->evtchn_upcall_pending = 1;
95 if (!vcpu_info->evtchn_upcall_mask)
96 force_evtchn_callback();
97 }
98 preempt_enable();
99 }
100 EXPORT_SYMBOL(unmask_evtchn);
102 int bind_listening_port_to_irqhandler(
103 unsigned int remote_domain,
104 irqreturn_t (*handler)(int, void *, struct pt_regs *),
105 unsigned long irqflags,
106 const char *devname,
107 void *dev_id)
108 {
109 struct evtchn_alloc_unbound alloc_unbound;
110 int err;
112 alloc_unbound.dom = DOMID_SELF;
113 alloc_unbound.remote_dom = remote_domain;
115 err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
116 &alloc_unbound);
117 if (err)
118 return err;
120 evtchns[alloc_unbound.port].handler = handler;
121 evtchns[alloc_unbound.port].dev_id = dev_id;
122 evtchns[alloc_unbound.port].close = 1;
123 unmask_evtchn(alloc_unbound.port);
124 return alloc_unbound.port;
125 }
126 EXPORT_SYMBOL(bind_listening_port_to_irqhandler);
128 int bind_caller_port_to_irqhandler(
129 unsigned int caller_port,
130 irqreturn_t (*handler)(int, void *, struct pt_regs *),
131 unsigned long irqflags,
132 const char *devname,
133 void *dev_id)
134 {
135 if (caller_port >= MAX_EVTCHN)
136 return -EINVAL;
137 evtchns[caller_port].handler = handler;
138 evtchns[caller_port].dev_id = dev_id;
139 evtchns[caller_port].close = 0;
140 unmask_evtchn(caller_port);
141 return caller_port;
142 }
143 EXPORT_SYMBOL(bind_caller_port_to_irqhandler);
145 void unbind_from_irqhandler(unsigned int evtchn, void *dev_id)
146 {
147 if (evtchn >= MAX_EVTCHN)
148 return;
150 mask_evtchn(evtchn);
151 evtchns[evtchn].handler = NULL;
153 if (evtchns[evtchn].close) {
154 struct evtchn_close close = { .port = evtchn };
155 HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
156 }
157 }
158 EXPORT_SYMBOL(unbind_from_irqhandler);
160 void notify_remote_via_irq(int irq)
161 {
162 int evtchn = irq;
163 notify_remote_via_evtchn(evtchn);
164 }
165 EXPORT_SYMBOL(notify_remote_via_irq);
167 irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
168 {
169 unsigned int l1i, port;
170 int cpu = smp_processor_id();
171 irqreturn_t(*handler) (int, void *, struct pt_regs *);
172 shared_info_t *s = shared_info_area;
173 vcpu_info_t *v = &s->vcpu_info[cpu];
174 unsigned long l1, l2;
176 v->evtchn_upcall_pending = 0;
177 /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
178 l1 = xchg(&v->evtchn_pending_sel, 0);
179 while (l1 != 0) {
180 l1i = __ffs(l1);
181 l1 &= ~(1 << l1i);
182 while ((l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i])) {
183 port = (l1i * BITS_PER_LONG) + __ffs(l2);
184 synch_clear_bit(port, &s->evtchn_pending[0]);
185 if ((handler = evtchns[port].handler) != NULL)
186 handler(port, evtchns[port].dev_id,
187 regs);
188 else
189 printk(KERN_WARNING "unexpected event channel "
190 "upcall on port %d!\n", port);
191 }
192 }
194 return IRQ_HANDLED;
195 }
197 void force_evtchn_callback(void)
198 {
199 (void)HYPERVISOR_xen_version(0, NULL);
200 }
201 EXPORT_SYMBOL(force_evtchn_callback);