direct-io.hg

view unmodified_drivers/linux-2.6/platform-pci/evtchn.c @ 11226:fc5736e0a2eb

[x86_64] Guests no longer set _PAGE_USER on kernel mappings.
This may allow guest kernels to be run outside ring 3 in future, and
also provides scope for optimisations today (e.g., using global bit on
user mappings).

Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Aug 22 15:26:40 2006 +0100 (2006-08-22)
parents 879918dbe77f
children 68a1b61ecd28
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, <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/config.h>
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <xen/evtchn.h>
35 #include <xen/interface/hvm/ioreq.h>
36 #include <xen/features.h>
37 #include "platform-pci.h"
39 void *shared_info_area;
41 #define MAX_EVTCHN 256
42 static struct
43 {
44 irqreturn_t(*handler) (int, void *, struct pt_regs *);
45 void *dev_id;
46 } evtchns[MAX_EVTCHN];
48 void mask_evtchn(int port)
49 {
50 shared_info_t *s = shared_info_area;
51 synch_set_bit(port, &s->evtchn_mask[0]);
52 }
53 EXPORT_SYMBOL(mask_evtchn);
55 void unmask_evtchn(int port)
56 {
57 unsigned int cpu;
58 shared_info_t *s = shared_info_area;
59 vcpu_info_t *vcpu_info;
61 preempt_disable();
62 cpu = smp_processor_id();
63 vcpu_info = &s->vcpu_info[cpu];
65 /* Slow path (hypercall) if this is a non-local port. We only
66 ever bind event channels to vcpu 0 in HVM guests. */
67 if (unlikely(cpu != 0)) {
68 evtchn_unmask_t op = { .port = port };
69 (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask,
70 &op);
71 preempt_enable();
72 return;
73 }
75 synch_clear_bit(port, &s->evtchn_mask[0]);
77 /*
78 * The following is basically the equivalent of
79 * 'hw_resend_irq'. Just like a real IO-APIC we 'lose the
80 * interrupt edge' if the channel is masked.
81 */
82 if (synch_test_bit(port, &s->evtchn_pending[0]) &&
83 !synch_test_and_set_bit(port / BITS_PER_LONG,
84 &vcpu_info->evtchn_pending_sel)) {
85 vcpu_info->evtchn_upcall_pending = 1;
86 if (!vcpu_info->evtchn_upcall_mask)
87 force_evtchn_callback();
88 }
89 preempt_enable();
90 }
91 EXPORT_SYMBOL(unmask_evtchn);
93 int
94 bind_evtchn_to_irqhandler(unsigned int evtchn,
95 irqreturn_t(*handler) (int, void *,
96 struct pt_regs *),
97 unsigned long irqflags, const char *devname,
98 void *dev_id)
99 {
100 if (evtchn >= MAX_EVTCHN)
101 return -EINVAL;
102 evtchns[evtchn].handler = handler;
103 evtchns[evtchn].dev_id = dev_id;
104 unmask_evtchn(evtchn);
105 return evtchn;
106 }
108 EXPORT_SYMBOL(bind_evtchn_to_irqhandler);
110 void unbind_from_irqhandler(unsigned int evtchn, void *dev_id)
111 {
112 if (evtchn >= MAX_EVTCHN)
113 return;
115 mask_evtchn(evtchn);
116 evtchns[evtchn].handler = NULL;
117 }
119 EXPORT_SYMBOL(unbind_from_irqhandler);
121 void notify_remote_via_irq(int irq)
122 {
123 int evtchn = irq;
124 notify_remote_via_evtchn(evtchn);
125 }
127 EXPORT_SYMBOL(notify_remote_via_irq);
129 irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
130 {
131 unsigned int l1i, l2i, port;
132 int cpu = smp_processor_id();
133 irqreturn_t(*handler) (int, void *, struct pt_regs *);
134 shared_info_t *s = shared_info_area;
135 vcpu_info_t *v = &s->vcpu_info[cpu];
136 unsigned long l1, l2;
138 v->evtchn_upcall_pending = 0;
139 /* NB. No need for a barrier here -- XCHG is a barrier
140 * on x86. */
141 l1 = xchg(&v->evtchn_pending_sel, 0);
142 while (l1 != 0)
143 {
144 l1i = __ffs(l1);
145 l1 &= ~(1 << l1i);
147 l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
148 while (l2 != 0)
149 {
150 l2i = __ffs(l2);
152 port = (l1i * BITS_PER_LONG) + l2i;
153 synch_clear_bit(port, &s->evtchn_pending[0]);
154 if ((handler = evtchns[port].handler) != NULL)
155 {
156 handler(port, evtchns[port].dev_id,
157 regs);
158 }
159 else
160 {
161 printk(KERN_WARNING "unexpected event channel upcall on port %d!\n", port);
162 }
163 l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
164 }
165 }
166 return IRQ_HANDLED;
167 }
169 void force_evtchn_callback(void)
170 {
171 evtchn_interrupt(0, NULL, NULL);
172 }
173 EXPORT_SYMBOL(force_evtchn_callback);