1/******************************************************************************
2 * xen_intr.h
3 *
4 * APIs for managing Xen event channel, virtual IRQ, and physical IRQ
5 * notifications.
6 *
7 * Copyright (c) 2004, K A Fraser
8 * Copyright (c) 2012, Spectra Logic Corporation
9 *
10 * This file may be distributed separately from the Linux kernel, or
11 * incorporated into other software packages, subject to the following license:
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this source file (the "Software"), to deal in the Software without
15 * restriction, including without limitation the rights to use, copy, modify,
16 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
17 * and to permit persons to whom the Software is furnished to do so, subject to
18 * the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 * IN THE SOFTWARE.
30 *
31 * $FreeBSD$
32 */
33#ifndef _XEN_INTR_H_
34#define _XEN_INTR_H_
35
36#include <xen/interface/event_channel.h>
37
38/** Registered Xen interrupt callback handle. */
39typedef void * xen_intr_handle_t;
40
41/** If non-zero, the hypervisor has been configured to use a direct vector */
42extern int xen_vector_callback_enabled;
43
44void xen_intr_handle_upcall(struct trapframe *trap_frame);
45
46/**
47 * Associate an already allocated local event channel port an interrupt
48 * handler.
49 *
50 * \param dev         The device making this bind request.
51 * \param local_port  The event channel to bind.
52 * \param filter      An interrupt filter handler.  Specify NULL
53 *                    to always dispatch to the ithread handler.
54 * \param handler     An interrupt ithread handler.  Optional (can
55 *                    specify NULL) if all necessary event actions
56 *                    are performed by filter.
57 * \param arg         Argument to present to both filter and handler.
58 * \param irqflags    Interrupt handler flags.  See sys/bus.h.
59 * \param handlep     Pointer to an opaque handle used to manage this
60 *                    registration.
61 *
62 * \returns  0 on success, otherwise an errno.
63 */
64int xen_intr_bind_local_port(device_t dev, evtchn_port_t local_port,
65	driver_filter_t filter, driver_intr_t handler, void *arg,
66	enum intr_type irqflags, xen_intr_handle_t *handlep);
67
68/**
69 * Allocate a local event channel port, accessible by the specified
70 * remote/foreign domain and, if successful, associate the port with
71 * the specified interrupt handler.
72 *
73 * \param dev            The device making this bind request.
74 * \param remote_domain  Remote domain grant permission to signal the
75 *                       newly allocated local port.
76 * \param filter         An interrupt filter handler.  Specify NULL
77 *                       to always dispatch to the ithread handler.
78 * \param handler        An interrupt ithread handler.  Optional (can
79 *                       specify NULL) if all necessary event actions
80 *                       are performed by filter.
81 * \param arg            Argument to present to both filter and handler.
82 * \param irqflags       Interrupt handler flags.  See sys/bus.h.
83 * \param handlep        Pointer to an opaque handle used to manage this
84 *                       registration.
85 *
86 * \returns  0 on success, otherwise an errno.
87 */
88int xen_intr_alloc_and_bind_local_port(device_t dev,
89	u_int remote_domain, driver_filter_t filter, driver_intr_t handler,
90	void *arg, enum intr_type irqflags, xen_intr_handle_t *handlep);
91
92/**
93 * Associate the specified interrupt handler with the remote event
94 * channel port specified by remote_domain and remote_port.
95 *
96 * \param dev            The device making this bind request.
97 * \param remote_domain  The domain peer for this event channel connection.
98 * \param remote_port    Remote domain's local port number for this event
99 *                       channel port.
100 * \param filter         An interrupt filter handler.  Specify NULL
101 *                       to always dispatch to the ithread handler.
102 * \param handler        An interrupt ithread handler.  Optional (can
103 *                       specify NULL) if all necessary event actions
104 *                       are performed by filter.
105 * \param arg            Argument to present to both filter and handler.
106 * \param irqflags       Interrupt handler flags.  See sys/bus.h.
107 * \param handlep        Pointer to an opaque handle used to manage this
108 *                       registration.
109 *
110 * \returns  0 on success, otherwise an errno.
111 */
112int xen_intr_bind_remote_port(device_t dev, u_int remote_domain,
113	evtchn_port_t remote_port, driver_filter_t filter,
114	driver_intr_t handler, void *arg, enum intr_type irqflags,
115	xen_intr_handle_t *handlep);
116
117/**
118 * Associate the specified interrupt handler with the specified Xen
119 * virtual interrupt source.
120 *
121 * \param dev       The device making this bind request.
122 * \param virq      The Xen virtual IRQ number for the Xen interrupt
123 *                  source being hooked.
124 * \param cpu       The cpu on which interrupt events should be delivered.
125 * \param filter    An interrupt filter handler.  Specify NULL
126 *                  to always dispatch to the ithread handler.
127 * \param handler   An interrupt ithread handler.  Optional (can
128 *                  specify NULL) if all necessary event actions
129 *                  are performed by filter.
130 * \param arg       Argument to present to both filter and handler.
131 * \param irqflags  Interrupt handler flags.  See sys/bus.h.
132 * \param handlep   Pointer to an opaque handle used to manage this
133 *                  registration.
134 *
135 * \returns  0 on success, otherwise an errno.
136 */
137int xen_intr_bind_virq(device_t dev, u_int virq, u_int cpu,
138	driver_filter_t filter, driver_intr_t handler,
139	void *arg, enum intr_type irqflags, xen_intr_handle_t *handlep);
140
141/**
142 * Allocate a local event channel port for servicing interprocessor
143 * interupts and, if successful, associate the port with the specified
144 * interrupt handler.
145 *
146 * \param cpu       The cpu receiving the IPI.
147 * \param filter    The interrupt filter servicing this IPI.
148 * \param irqflags  Interrupt handler flags.  See sys/bus.h.
149 * \param handlep   Pointer to an opaque handle used to manage this
150 *                  registration.
151 *
152 * \returns  0 on success, otherwise an errno.
153 */
154int xen_intr_alloc_and_bind_ipi(u_int cpu,
155	driver_filter_t filter, enum intr_type irqflags,
156	xen_intr_handle_t *handlep);
157
158/**
159 * Register a physical interrupt vector and setup the interrupt source.
160 *
161 * \param vector        The global vector to use.
162 * \param trig          Default trigger method.
163 * \param pol           Default polarity of the interrupt.
164 *
165 * \returns  0 on success, otherwise an errno.
166 */
167int xen_register_pirq(int vector, enum intr_trigger trig,
168	enum intr_polarity pol);
169
170/**
171 * Unbind an interrupt handler from its interrupt source.
172 *
173 * \param handlep  A pointer to the opaque handle that was initialized
174 *		   at the time the interrupt source was bound.
175 *
176 * \returns  0 on success, otherwise an errno.
177 *
178 * \note  The event channel, if any, that was allocated at bind time is
179 *        closed upon successful return of this method.
180 *
181 * \note  It is always safe to call xen_intr_unbind() on a handle that
182 *        has been initilized to NULL.
183 */
184void xen_intr_unbind(xen_intr_handle_t *handle);
185
186/**
187 * Add a description to an interrupt handler.
188 *
189 * \param handle  The opaque handle that was initialized at the time
190 *		  the interrupt source was bound.
191 *
192 * \param fmt     The sprintf compatible format string for the description,
193 *                followed by optional sprintf arguments.
194 *
195 * \returns  0 on success, otherwise an errno.
196 */
197int
198xen_intr_describe(xen_intr_handle_t port_handle, const char *fmt, ...)
199	__attribute__((format(printf, 2, 3)));
200
201/**
202 * Signal the remote peer of an interrupt source associated with an
203 * event channel port.
204 *
205 * \param handle  The opaque handle that was initialized at the time
206 *                the interrupt source was bound.
207 *
208 * \note  For xen interrupt sources other than event channel ports,
209 *        this method takes no action.
210 */
211void xen_intr_signal(xen_intr_handle_t handle);
212
213/**
214 * Get the local event channel port number associated with this interrupt
215 * source.
216 *
217 * \param handle  The opaque handle that was initialized at the time
218 *                the interrupt source was bound.
219 *
220 * \returns  0 if the handle is invalid, otherwise positive port number.
221 */
222evtchn_port_t xen_intr_port(xen_intr_handle_t handle);
223
224/**
225 * Setup MSI vector interrupt(s).
226 *
227 * \param dev     The device that requests the binding.
228 *
229 * \param vector  Requested initial vector to bind the MSI interrupt(s) to.
230 *
231 * \param count   Number of vectors to allocate.
232 *
233 * \returns  0 on success, otherwise an errno.
234 */
235int xen_register_msi(device_t dev, int vector, int count);
236
237/**
238 * Teardown a MSI vector interrupt.
239 *
240 * \param vector  Requested vector to release.
241 *
242 * \returns  0 on success, otherwise an errno.
243 */
244int xen_release_msi(int vector);
245
246/**
247 * Bind an event channel port with a handler
248 *
249 * \param dev       The device making this bind request.
250 * \param filter    An interrupt filter handler.  Specify NULL
251 *                  to always dispatch to the ithread handler.
252 * \param handler   An interrupt ithread handler.  Optional (can
253 *                  specify NULL) if all necessary event actions
254 *                  are performed by filter.
255 * \param arg       Argument to present to both filter and handler.
256 * \param irqflags  Interrupt handler flags.  See sys/bus.h.
257 * \param handle    Opaque handle used to manage this registration.
258 *
259 * \returns  0 on success, otherwise an errno.
260 */
261int xen_intr_add_handler(const char *name, driver_filter_t filter,
262	driver_intr_t handler, void *arg, enum intr_type flags,
263	xen_intr_handle_t handle);
264
265/**
266 * Get a reference to an event channel port
267 *
268 * \param port	    Event channel port to which we get a reference.
269 * \param handlep   Pointer to an opaque handle used to manage this
270 *                  registration.
271 *
272 * \returns  0 on success, otherwise an errno.
273 */
274int xen_intr_get_evtchn_from_port(evtchn_port_t port,
275	xen_intr_handle_t *handlep);
276
277/**
278 * Register the IO-APIC PIRQs when running in legacy PVH Dom0 mode.
279 *
280 * \param pic	    PIC instance.
281 *
282 * NB: this should be removed together with the support for legacy PVH mode.
283 */
284struct pic;
285void xenpv_register_pirqs(struct pic *pic);
286
287#endif /* _XEN_INTR_H_ */
288