summaryrefslogtreecommitdiffstats
path: root/sys/xen
diff options
context:
space:
mode:
Diffstat (limited to 'sys/xen')
-rw-r--r--sys/xen/evtchn.h135
-rw-r--r--sys/xen/evtchn/evtchn.c1141
-rw-r--r--sys/xen/evtchn/evtchn_dev.c57
-rw-r--r--sys/xen/evtchn/evtchnvar.h105
-rw-r--r--sys/xen/features.c2
-rw-r--r--sys/xen/gnttab.c12
-rw-r--r--sys/xen/gnttab.h7
-rw-r--r--sys/xen/hvm.h4
-rw-r--r--sys/xen/interface/event_channel.h3
-rw-r--r--sys/xen/xen-os.h95
-rw-r--r--sys/xen/xen_intr.h295
-rw-r--r--sys/xen/xenbus/xenbus.c39
-rw-r--r--sys/xen/xenbus/xenbus_if.m3
-rw-r--r--sys/xen/xenbus/xenbusb_front.c2
-rw-r--r--sys/xen/xenbus/xenbusvar.h35
-rw-r--r--sys/xen/xenstore/xenstore.c30
-rw-r--r--sys/xen/xenstore/xenstore_dev.c2
-rw-r--r--sys/xen/xenstore/xenstorevar.h2
18 files changed, 518 insertions, 1451 deletions
diff --git a/sys/xen/evtchn.h b/sys/xen/evtchn.h
index 721742f..00fa67e 100644
--- a/sys/xen/evtchn.h
+++ b/sys/xen/evtchn.h
@@ -1,94 +1,87 @@
/******************************************************************************
* evtchn.h
*
- * Communication via Xen event channels.
- * Also definitions for the device that demuxes notifications to userspace.
+ * Interface to /dev/xen/evtchn.
*
- * Copyright (c) 2004, K A Fraser
+ * Copyright (c) 2003-2005, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
*
* $FreeBSD$
*/
-#ifndef __ASM_EVTCHN_H__
-#define __ASM_EVTCHN_H__
-#include <machine/pcpu.h>
-#include <xen/hypervisor.h>
-#include <machine/xen/synch_bitops.h>
-#include <machine/frame.h>
+#ifndef __XEN_EVTCHN_H__
+#define __XEN_EVTCHN_H__
/*
- * LOW-LEVEL DEFINITIONS
+ * Bind a fresh port to VIRQ @virq.
*/
+#define IOCTL_EVTCHN_BIND_VIRQ \
+ _IOWR('E', 4, struct ioctl_evtchn_bind_virq)
+struct ioctl_evtchn_bind_virq {
+ unsigned int virq;
+ unsigned int port;
+};
/*
- * Unlike notify_remote_via_evtchn(), this is safe to use across
- * save/restore. Notifications on a broken connection are silently dropped.
+ * Bind a fresh port to remote <@remote_domain, @remote_port>.
*/
-void notify_remote_via_irq(int irq);
-
-
-/* Entry point for notifications into Linux subsystems. */
-void evtchn_do_upcall(struct trapframe *frame);
-
-/* Entry point for notifications into the userland character device. */
-void evtchn_device_upcall(int port);
-
-void mask_evtchn(int port);
-
-void unmask_evtchn(int port);
-
-#ifdef SMP
-void rebind_evtchn_to_cpu(int port, unsigned int cpu);
-#else
-#define rebind_evtchn_to_cpu(port, cpu) ((void)0)
-#endif
-
-static inline
-int test_and_set_evtchn_mask(int port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- return synch_test_and_set_bit(port, s->evtchn_mask);
-}
-
-static inline void
-clear_evtchn(int port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- synch_clear_bit(port, &s->evtchn_pending[0]);
-}
-
-static inline void
-notify_remote_via_evtchn(int port)
-{
- struct evtchn_send send = { .port = port };
- (void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send);
-}
+#define IOCTL_EVTCHN_BIND_INTERDOMAIN \
+ _IOWR('E', 5, struct ioctl_evtchn_bind_interdomain)
+struct ioctl_evtchn_bind_interdomain {
+ unsigned int remote_domain, remote_port;
+ unsigned int port;
+};
/*
- * Use these to access the event channel underlying the IRQ handle returned
- * by bind_*_to_irqhandler().
+ * Allocate a fresh port for binding to @remote_domain.
*/
-int irq_to_evtchn_port(int irq);
-
-void ipi_pcpu(unsigned int cpu, int vector);
+#define IOCTL_EVTCHN_BIND_UNBOUND_PORT \
+ _IOWR('E', 6, struct ioctl_evtchn_bind_unbound_port)
+struct ioctl_evtchn_bind_unbound_port {
+ unsigned int remote_domain;
+ unsigned int port;
+};
/*
- * CHARACTER-DEVICE DEFINITIONS
+ * Unbind previously allocated @port.
*/
+#define IOCTL_EVTCHN_UNBIND \
+ _IOW('E', 7, struct ioctl_evtchn_unbind)
+struct ioctl_evtchn_unbind {
+ unsigned int port;
+};
-#define PORT_NORMAL 0x0000
-#define PORT_EXCEPTION 0x8000
-#define PORTIDX_MASK 0x7fff
-
-/* /dev/xen/evtchn resides at device number major=10, minor=200 */
-#define EVTCHN_MINOR 200
+/*
+ * Send event to previously allocated @port.
+ */
+#define IOCTL_EVTCHN_NOTIFY \
+ _IOW('E', 8, struct ioctl_evtchn_notify)
+struct ioctl_evtchn_notify {
+ unsigned int port;
+};
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET _IO('E', 1)
-/* EVTCHN_BIND: Bind to the specified event-channel port. */
-#define EVTCHN_BIND _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
+/* Clear and reinitialise the event buffer. Clear error condition. */
+#define IOCTL_EVTCHN_RESET \
+ _IO('E', 9)
-#endif /* __ASM_EVTCHN_H__ */
+#endif /* __XEN_EVTCHN_H__ */
diff --git a/sys/xen/evtchn/evtchn.c b/sys/xen/evtchn/evtchn.c
deleted file mode 100644
index baff9aa..0000000
--- a/sys/xen/evtchn/evtchn.c
+++ /dev/null
@@ -1,1141 +0,0 @@
-/******************************************************************************
- * evtchn.c
- *
- * Communication via Xen event channels.
- *
- * Copyright (c) 2002-2005, K A Fraser
- * Copyright (c) 2005-2006 Kip Macy
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/limits.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/interrupt.h>
-#include <sys/pcpu.h>
-#include <sys/smp.h>
-
-#include <machine/cpufunc.h>
-#include <machine/intr_machdep.h>
-
-#include <machine/xen/xen-os.h>
-#include <machine/xen/xenvar.h>
-#include <xen/xen_intr.h>
-#include <machine/xen/synch_bitops.h>
-#include <xen/evtchn.h>
-#include <xen/hypervisor.h>
-#include <sys/smp.h>
-
-#include <xen/xen_intr.h>
-#include <xen/evtchn.h>
-
-static inline unsigned long __ffs(unsigned long word)
-{
- __asm__("bsfl %1,%0"
- :"=r" (word)
- :"rm" (word));
- return word;
-}
-
-/*
- * irq_mapping_update_lock: in order to allow an interrupt to occur in a critical
- * section, to set pcpu->ipending (etc...) properly, we
- * must be able to get the icu lock, so it can't be
- * under witness.
- */
-static struct mtx irq_mapping_update_lock;
-MTX_SYSINIT(irq_mapping_update_lock, &irq_mapping_update_lock, "xp", MTX_SPIN);
-
-static struct xenpic *xp;
-struct xenpic_intsrc {
- struct intsrc xp_intsrc;
- void *xp_cookie;
- uint8_t xp_vector;
- boolean_t xp_masked;
-};
-
-struct xenpic {
- struct pic *xp_dynirq_pic;
- struct pic *xp_pirq_pic;
- uint16_t xp_numintr;
- struct xenpic_intsrc xp_pins[0];
-};
-
-#define TODO printf("%s: not implemented!\n", __func__)
-
-/* IRQ <-> event-channel mappings. */
-static int evtchn_to_irq[NR_EVENT_CHANNELS];
-
-/* Packed IRQ information: binding type, sub-type index, and event channel. */
-static uint32_t irq_info[NR_IRQS];
-/* Binding types. */
-enum {
- IRQT_UNBOUND,
- IRQT_PIRQ,
- IRQT_VIRQ,
- IRQT_IPI,
- IRQT_LOCAL_PORT,
- IRQT_CALLER_PORT,
- _IRQT_COUNT
-
-};
-
-
-#define _IRQT_BITS 4
-#define _EVTCHN_BITS 12
-#define _INDEX_BITS (32 - _IRQT_BITS - _EVTCHN_BITS)
-
-/* Constructor for packed IRQ information. */
-static inline uint32_t
-mk_irq_info(uint32_t type, uint32_t index, uint32_t evtchn)
-{
-
- return ((type << (32 - _IRQT_BITS)) | (index << _EVTCHN_BITS) | evtchn);
-}
-
-/* Constructor for packed IRQ information. */
-
-/* Convenient shorthand for packed representation of an unbound IRQ. */
-#define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0)
-
-/*
- * Accessors for packed IRQ information.
- */
-
-static inline unsigned int evtchn_from_irq(int irq)
-{
- return irq_info[irq] & ((1U << _EVTCHN_BITS) - 1);
-}
-
-static inline unsigned int index_from_irq(int irq)
-{
- return (irq_info[irq] >> _EVTCHN_BITS) & ((1U << _INDEX_BITS) - 1);
-}
-
-static inline unsigned int type_from_irq(int irq)
-{
- return irq_info[irq] >> (32 - _IRQT_BITS);
-}
-
-
-/* IRQ <-> VIRQ mapping. */
-
-/* IRQ <-> IPI mapping. */
-#ifndef NR_IPIS
-#ifdef SMP
-#error "NR_IPIS not defined"
-#endif
-#define NR_IPIS 1
-#endif
-
-/* Bitmap indicating which PIRQs require Xen to be notified on unmask. */
-static unsigned long pirq_needs_unmask_notify[NR_PIRQS/sizeof(unsigned long)];
-
-/* Reference counts for bindings to IRQs. */
-static int irq_bindcount[NR_IRQS];
-
-#define VALID_EVTCHN(_chn) ((_chn) != 0)
-
-#ifdef SMP
-
-static uint8_t cpu_evtchn[NR_EVENT_CHANNELS];
-static unsigned long cpu_evtchn_mask[XEN_LEGACY_MAX_VCPUS][NR_EVENT_CHANNELS/LONG_BIT];
-
-#define active_evtchns(cpu,sh,idx) \
- ((sh)->evtchn_pending[idx] & \
- cpu_evtchn_mask[cpu][idx] & \
- ~(sh)->evtchn_mask[idx])
-
-static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
-{
- clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
- set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
- cpu_evtchn[chn] = cpu;
-}
-
-static void init_evtchn_cpu_bindings(void)
-{
- /* By default all event channels notify CPU#0. */
- memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
- memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0]));
-}
-
-#define cpu_from_evtchn(evtchn) (cpu_evtchn[evtchn])
-
-#else
-
-#define active_evtchns(cpu,sh,idx) \
- ((sh)->evtchn_pending[idx] & \
- ~(sh)->evtchn_mask[idx])
-#define bind_evtchn_to_cpu(chn,cpu) ((void)0)
-#define init_evtchn_cpu_bindings() ((void)0)
-#define cpu_from_evtchn(evtchn) (0)
-
-#endif
-
-
-/*
- * Force a proper event-channel callback from Xen after clearing the
- * callback mask. We do this in a very simple manner, by making a call
- * down into Xen. The pending flag will be checked by Xen on return.
- */
-void force_evtchn_callback(void)
-{
- (void)HYPERVISOR_xen_version(0, NULL);
-}
-
-void
-evtchn_do_upcall(struct trapframe *frame)
-{
- unsigned long l1, l2;
- unsigned int l1i, l2i, port;
- int irq, cpu;
- shared_info_t *s;
- vcpu_info_t *vcpu_info;
-
- cpu = PCPU_GET(cpuid);
- s = HYPERVISOR_shared_info;
- vcpu_info = &s->vcpu_info[cpu];
-
- vcpu_info->evtchn_upcall_pending = 0;
-
- /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
- l1 = xen_xchg(&vcpu_info->evtchn_pending_sel, 0);
-
- while (l1 != 0) {
- l1i = __ffs(l1);
- l1 &= ~(1 << l1i);
-
- while ((l2 = active_evtchns(cpu, s, l1i)) != 0) {
- l2i = __ffs(l2);
-
- port = (l1i * LONG_BIT) + l2i;
- if ((irq = evtchn_to_irq[port]) != -1) {
- struct intsrc *isrc = intr_lookup_source(irq);
- /*
- * ack
- */
- mask_evtchn(port);
- clear_evtchn(port);
-
- intr_execute_handlers(isrc, frame);
- } else {
- evtchn_device_upcall(port);
- }
- }
- }
-}
-
-/*
- * Send an IPI from the current CPU to the destination CPU.
- */
-void
-ipi_pcpu(unsigned int cpu, int vector)
-{
- int irq;
-
- irq = pcpu_find(cpu)->pc_ipi_to_irq[vector];
-
- notify_remote_via_irq(irq);
-}
-
-static int
-find_unbound_irq(void)
-{
- int dynirq, irq;
-
- for (dynirq = 0; dynirq < NR_IRQS; dynirq++) {
- irq = dynirq_to_irq(dynirq);
- if (irq_bindcount[irq] == 0)
- break;
- }
-
- if (irq == NR_IRQS)
- panic("No available IRQ to bind to: increase NR_IRQS!\n");
-
- return (irq);
-}
-
-static int
-bind_caller_port_to_irq(unsigned int caller_port, int * port)
-{
- int irq;
-
- mtx_lock_spin(&irq_mapping_update_lock);
-
- if ((irq = evtchn_to_irq[caller_port]) == -1) {
- if ((irq = find_unbound_irq()) < 0)
- goto out;
-
- evtchn_to_irq[caller_port] = irq;
- irq_info[irq] = mk_irq_info(IRQT_CALLER_PORT, 0, caller_port);
- }
-
- irq_bindcount[irq]++;
- *port = caller_port;
-
- out:
- mtx_unlock_spin(&irq_mapping_update_lock);
- return irq;
-}
-
-static int
-bind_local_port_to_irq(unsigned int local_port, int * port)
-{
- int irq;
-
- mtx_lock_spin(&irq_mapping_update_lock);
-
- KASSERT(evtchn_to_irq[local_port] == -1,
- ("evtchn_to_irq inconsistent"));
-
- if ((irq = find_unbound_irq()) < 0) {
- struct evtchn_close close = { .port = local_port };
- HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
-
- goto out;
- }
-
- evtchn_to_irq[local_port] = irq;
- irq_info[irq] = mk_irq_info(IRQT_LOCAL_PORT, 0, local_port);
- irq_bindcount[irq]++;
- *port = local_port;
-
- out:
- mtx_unlock_spin(&irq_mapping_update_lock);
- return irq;
-}
-
-static int
-bind_listening_port_to_irq(unsigned int remote_domain, int * port)
-{
- struct evtchn_alloc_unbound alloc_unbound;
- int err;
-
- alloc_unbound.dom = DOMID_SELF;
- alloc_unbound.remote_dom = remote_domain;
-
- err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
- &alloc_unbound);
-
- return err ? : bind_local_port_to_irq(alloc_unbound.port, port);
-}
-
-static int
-bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
- unsigned int remote_port, int * port)
-{
- struct evtchn_bind_interdomain bind_interdomain;
- int err;
-
- bind_interdomain.remote_dom = remote_domain;
- bind_interdomain.remote_port = remote_port;
-
- err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
- &bind_interdomain);
-
- return err ? : bind_local_port_to_irq(bind_interdomain.local_port, port);
-}
-
-static int
-bind_virq_to_irq(unsigned int virq, unsigned int cpu, int * port)
-{
- struct evtchn_bind_virq bind_virq;
- int evtchn = 0, irq;
-
- mtx_lock_spin(&irq_mapping_update_lock);
-
- if ((irq = pcpu_find(cpu)->pc_virq_to_irq[virq]) == -1) {
- if ((irq = find_unbound_irq()) < 0)
- goto out;
-
- bind_virq.virq = virq;
- bind_virq.vcpu = cpu;
- HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq);
-
- evtchn = bind_virq.port;
-
- evtchn_to_irq[evtchn] = irq;
- irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
-
- pcpu_find(cpu)->pc_virq_to_irq[virq] = irq;
-
- bind_evtchn_to_cpu(evtchn, cpu);
- }
-
- irq_bindcount[irq]++;
- *port = evtchn;
-out:
- mtx_unlock_spin(&irq_mapping_update_lock);
-
- return irq;
-}
-
-
-static int
-bind_ipi_to_irq(unsigned int ipi, unsigned int cpu, int * port)
-{
- struct evtchn_bind_ipi bind_ipi;
- int irq;
- int evtchn = 0;
-
- mtx_lock_spin(&irq_mapping_update_lock);
-
- if ((irq = pcpu_find(cpu)->pc_ipi_to_irq[ipi]) == -1) {
- if ((irq = find_unbound_irq()) < 0)
- goto out;
-
- bind_ipi.vcpu = cpu;
- HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi);
- evtchn = bind_ipi.port;
-
- evtchn_to_irq[evtchn] = irq;
- irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
-
- pcpu_find(cpu)->pc_ipi_to_irq[ipi] = irq;
-
- bind_evtchn_to_cpu(evtchn, cpu);
- }
- irq_bindcount[irq]++;
- *port = evtchn;
-out:
-
- mtx_unlock_spin(&irq_mapping_update_lock);
-
- return irq;
-}
-
-
-static void
-unbind_from_irq(int irq)
-{
- struct evtchn_close close;
- int evtchn = evtchn_from_irq(irq);
- int cpu;
-
- mtx_lock_spin(&irq_mapping_update_lock);
-
- if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) {
- close.port = evtchn;
- HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
-
- switch (type_from_irq(irq)) {
- case IRQT_VIRQ:
- cpu = cpu_from_evtchn(evtchn);
- pcpu_find(cpu)->pc_virq_to_irq[index_from_irq(irq)] = -1;
- break;
- case IRQT_IPI:
- cpu = cpu_from_evtchn(evtchn);
- pcpu_find(cpu)->pc_ipi_to_irq[index_from_irq(irq)] = -1;
- break;
- default:
- break;
- }
-
- /* Closed ports are implicitly re-bound to VCPU0. */
- bind_evtchn_to_cpu(evtchn, 0);
-
- evtchn_to_irq[evtchn] = -1;
- irq_info[irq] = IRQ_UNBOUND;
- }
-
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-int
-bind_caller_port_to_irqhandler(unsigned int caller_port,
- const char *devname, driver_intr_t handler, void *arg,
- unsigned long irqflags, unsigned int *irqp)
-{
- unsigned int irq;
- int port = -1;
- int error;
-
- irq = bind_caller_port_to_irq(caller_port, &port);
- intr_register_source(&xp->xp_pins[irq].xp_intsrc);
- error = intr_add_handler(devname, irq, NULL, handler, arg, irqflags,
- &xp->xp_pins[irq].xp_cookie);
-
- if (error) {
- unbind_from_irq(irq);
- return (error);
- }
- if (port != -1)
- unmask_evtchn(port);
-
- if (irqp)
- *irqp = irq;
-
- return (0);
-}
-
-int
-bind_listening_port_to_irqhandler(unsigned int remote_domain,
- const char *devname, driver_intr_t handler, void *arg,
- unsigned long irqflags, unsigned int *irqp)
-{
- unsigned int irq;
- int port = -1;
- int error;
-
- irq = bind_listening_port_to_irq(remote_domain, &port);
- intr_register_source(&xp->xp_pins[irq].xp_intsrc);
- error = intr_add_handler(devname, irq, NULL, handler, arg, irqflags,
- &xp->xp_pins[irq].xp_cookie);
- if (error) {
- unbind_from_irq(irq);
- return (error);
- }
- if (port != -1)
- unmask_evtchn(port);
- if (irqp)
- *irqp = irq;
-
- return (0);
-}
-
-int
-bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
- unsigned int remote_port, const char *devname,
- driver_intr_t handler, void *arg, unsigned long irqflags,
- unsigned int *irqp)
-{
- unsigned int irq;
- int port = -1;
- int error;
-
- irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port, &port);
- intr_register_source(&xp->xp_pins[irq].xp_intsrc);
- error = intr_add_handler(devname, irq, NULL, handler, arg,
- irqflags, &xp->xp_pins[irq].xp_cookie);
- if (error) {
- unbind_from_irq(irq);
- return (error);
- }
- if (port != -1)
- unmask_evtchn(port);
-
- if (irqp)
- *irqp = irq;
- return (0);
-}
-
-int
-bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
- const char *devname, driver_filter_t filter, driver_intr_t handler,
- void *arg, unsigned long irqflags, unsigned int *irqp)
-{
- unsigned int irq;
- int port = -1;
- int error;
-
- irq = bind_virq_to_irq(virq, cpu, &port);
- intr_register_source(&xp->xp_pins[irq].xp_intsrc);
- error = intr_add_handler(devname, irq, filter, handler,
- arg, irqflags, &xp->xp_pins[irq].xp_cookie);
- if (error) {
- unbind_from_irq(irq);
- return (error);
- }
- if (port != -1)
- unmask_evtchn(port);
-
- if (irqp)
- *irqp = irq;
- return (0);
-}
-
-int
-bind_ipi_to_irqhandler(unsigned int ipi, unsigned int cpu,
- const char *devname, driver_filter_t filter,
- unsigned long irqflags, unsigned int *irqp)
-{
- unsigned int irq;
- int port = -1;
- int error;
-
- irq = bind_ipi_to_irq(ipi, cpu, &port);
- intr_register_source(&xp->xp_pins[irq].xp_intsrc);
- error = intr_add_handler(devname, irq, filter, NULL,
- NULL, irqflags, &xp->xp_pins[irq].xp_cookie);
- if (error) {
- unbind_from_irq(irq);
- return (error);
- }
- if (port != -1)
- unmask_evtchn(port);
-
- if (irqp)
- *irqp = irq;
- return (0);
-}
-
-void
-unbind_from_irqhandler(unsigned int irq)
-{
- intr_remove_handler(xp->xp_pins[irq].xp_cookie);
- unbind_from_irq(irq);
-}
-
-#if 0
-/* Rebind an evtchn so that it gets delivered to a specific cpu */
-static void
-rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
-{
- evtchn_op_t op = { .cmd = EVTCHNOP_bind_vcpu };
- int evtchn;
-
- mtx_lock_spin(&irq_mapping_update_lock);
-
- evtchn = evtchn_from_irq(irq);
- if (!VALID_EVTCHN(evtchn)) {
- mtx_unlock_spin(&irq_mapping_update_lock);
- return;
- }
-
- /* Send future instances of this interrupt to other vcpu. */
- bind_vcpu.port = evtchn;
- bind_vcpu.vcpu = tcpu;
-
- /*
- * If this fails, it usually just indicates that we're dealing with a
- * virq or IPI channel, which don't actually need to be rebound. Ignore
- * it, but don't do the xenlinux-level rebind in that case.
- */
- if (HYPERVISOR_event_channel_op(&op) >= 0)
- bind_evtchn_to_cpu(evtchn, tcpu);
-
- mtx_unlock_spin(&irq_mapping_update_lock);
-
-}
-
-static void set_affinity_irq(unsigned irq, cpumask_t dest)
-{
- unsigned tcpu = ffs(dest) - 1;
- rebind_irq_to_cpu(irq, tcpu);
-}
-#endif
-
-/*
- * Interface to generic handling in intr_machdep.c
- */
-
-
-/*------------ interrupt handling --------------------------------------*/
-#define TODO printf("%s: not implemented!\n", __func__)
-
-
-static void xenpic_dynirq_enable_source(struct intsrc *isrc);
-static void xenpic_dynirq_disable_source(struct intsrc *isrc, int);
-static void xenpic_dynirq_eoi_source(struct intsrc *isrc);
-static void xenpic_dynirq_enable_intr(struct intsrc *isrc);
-static void xenpic_dynirq_disable_intr(struct intsrc *isrc);
-
-static void xenpic_pirq_enable_source(struct intsrc *isrc);
-static void xenpic_pirq_disable_source(struct intsrc *isrc, int);
-static void xenpic_pirq_eoi_source(struct intsrc *isrc);
-static void xenpic_pirq_enable_intr(struct intsrc *isrc);
-
-
-static int xenpic_vector(struct intsrc *isrc);
-static int xenpic_source_pending(struct intsrc *isrc);
-static void xenpic_suspend(struct pic* pic);
-static void xenpic_resume(struct pic* pic);
-static int xenpic_assign_cpu(struct intsrc *, u_int apic_id);
-
-
-struct pic xenpic_dynirq_template = {
- .pic_enable_source = xenpic_dynirq_enable_source,
- .pic_disable_source = xenpic_dynirq_disable_source,
- .pic_eoi_source = xenpic_dynirq_eoi_source,
- .pic_enable_intr = xenpic_dynirq_enable_intr,
- .pic_disable_intr = xenpic_dynirq_disable_intr,
- .pic_vector = xenpic_vector,
- .pic_source_pending = xenpic_source_pending,
- .pic_suspend = xenpic_suspend,
- .pic_resume = xenpic_resume
-};
-
-struct pic xenpic_pirq_template = {
- .pic_enable_source = xenpic_pirq_enable_source,
- .pic_disable_source = xenpic_pirq_disable_source,
- .pic_eoi_source = xenpic_pirq_eoi_source,
- .pic_enable_intr = xenpic_pirq_enable_intr,
- .pic_vector = xenpic_vector,
- .pic_source_pending = xenpic_source_pending,
- .pic_suspend = xenpic_suspend,
- .pic_resume = xenpic_resume,
- .pic_assign_cpu = xenpic_assign_cpu
-};
-
-
-
-void
-xenpic_dynirq_enable_source(struct intsrc *isrc)
-{
- unsigned int irq;
- struct xenpic_intsrc *xp;
-
- xp = (struct xenpic_intsrc *)isrc;
-
- mtx_lock_spin(&irq_mapping_update_lock);
- if (xp->xp_masked) {
- irq = xenpic_vector(isrc);
- unmask_evtchn(evtchn_from_irq(irq));
- xp->xp_masked = FALSE;
- }
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-static void
-xenpic_dynirq_disable_source(struct intsrc *isrc, int foo)
-{
- unsigned int irq;
- struct xenpic_intsrc *xp;
-
- xp = (struct xenpic_intsrc *)isrc;
-
- mtx_lock_spin(&irq_mapping_update_lock);
- if (!xp->xp_masked) {
- irq = xenpic_vector(isrc);
- mask_evtchn(evtchn_from_irq(irq));
- xp->xp_masked = TRUE;
- }
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-static void
-xenpic_dynirq_enable_intr(struct intsrc *isrc)
-{
- unsigned int irq;
- struct xenpic_intsrc *xp;
-
- xp = (struct xenpic_intsrc *)isrc;
- mtx_lock_spin(&irq_mapping_update_lock);
- xp->xp_masked = 0;
- irq = xenpic_vector(isrc);
- unmask_evtchn(evtchn_from_irq(irq));
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-static void
-xenpic_dynirq_disable_intr(struct intsrc *isrc)
-{
- unsigned int irq;
- struct xenpic_intsrc *xp;
-
- xp = (struct xenpic_intsrc *)isrc;
- mtx_lock_spin(&irq_mapping_update_lock);
- irq = xenpic_vector(isrc);
- mask_evtchn(evtchn_from_irq(irq));
- xp->xp_masked = 1;
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-static void
-xenpic_dynirq_eoi_source(struct intsrc *isrc)
-{
- unsigned int irq;
- struct xenpic_intsrc *xp;
-
- xp = (struct xenpic_intsrc *)isrc;
- mtx_lock_spin(&irq_mapping_update_lock);
- xp->xp_masked = 0;
- irq = xenpic_vector(isrc);
- unmask_evtchn(evtchn_from_irq(irq));
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-static int
-xenpic_vector(struct intsrc *isrc)
-{
- struct xenpic_intsrc *pin;
-
- pin = (struct xenpic_intsrc *)isrc;
- //printf("xenpic_vector(): isrc=%p,vector=%u\n", pin, pin->xp_vector);
-
- return (pin->xp_vector);
-}
-
-static int
-xenpic_source_pending(struct intsrc *isrc)
-{
- struct xenpic_intsrc *pin = (struct xenpic_intsrc *)isrc;
-
- /* XXXEN: TODO */
- printf("xenpic_source_pending(): vector=%x,masked=%x\n",
- pin->xp_vector, pin->xp_masked);
-
-/* notify_remote_via_evtchn(pin->xp_vector); // XXX RS: Is this correct? */
- return 0;
-}
-
-static void
-xenpic_suspend(struct pic* pic)
-{
- TODO;
-}
-
-static void
-xenpic_resume(struct pic* pic)
-{
- TODO;
-}
-
-static int
-xenpic_assign_cpu(struct intsrc *isrc, u_int apic_id)
-{
- TODO;
- return (EOPNOTSUPP);
-}
-
-void
-notify_remote_via_irq(int irq)
-{
- int evtchn = evtchn_from_irq(irq);
-
- if (VALID_EVTCHN(evtchn))
- notify_remote_via_evtchn(evtchn);
- else
- panic("invalid evtchn %d", irq);
-}
-
-/* required for support of physical devices */
-static inline void
-pirq_unmask_notify(int pirq)
-{
- struct physdev_eoi eoi = { .irq = pirq };
-
- if (unlikely(test_bit(pirq, &pirq_needs_unmask_notify[0]))) {
- (void)HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
- }
-}
-
-static inline void
-pirq_query_unmask(int pirq)
-{
- struct physdev_irq_status_query irq_status_query;
-
- irq_status_query.irq = pirq;
- (void)HYPERVISOR_physdev_op(PHYSDEVOP_IRQ_STATUS_QUERY, &irq_status_query);
- clear_bit(pirq, &pirq_needs_unmask_notify[0]);
- if ( irq_status_query.flags & PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY )
- set_bit(pirq, &pirq_needs_unmask_notify[0]);
-}
-
-/*
- * On startup, if there is no action associated with the IRQ then we are
- * probing. In this case we should not share with others as it will confuse us.
- */
-#define probing_irq(_irq) (intr_lookup_source(irq) == NULL)
-
-static void
-xenpic_pirq_enable_intr(struct intsrc *isrc)
-{
- struct evtchn_bind_pirq bind_pirq;
- int evtchn;
- unsigned int irq;
-
- mtx_lock_spin(&irq_mapping_update_lock);
- irq = xenpic_vector(isrc);
- evtchn = evtchn_from_irq(irq);
-
- if (VALID_EVTCHN(evtchn))
- goto out;
-
- bind_pirq.pirq = irq;
- /* NB. We are happy to share unless we are probing. */
- bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
-
- if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq) != 0) {
-#ifndef XEN_PRIVILEGED_GUEST
- panic("unexpected pirq call");
-#endif
- if (!probing_irq(irq)) /* Some failures are expected when probing. */
- printf("Failed to obtain physical IRQ %d\n", irq);
- mtx_unlock_spin(&irq_mapping_update_lock);
- return;
- }
- evtchn = bind_pirq.port;
-
- pirq_query_unmask(irq_to_pirq(irq));
-
- bind_evtchn_to_cpu(evtchn, 0);
- evtchn_to_irq[evtchn] = irq;
- irq_info[irq] = mk_irq_info(IRQT_PIRQ, irq, evtchn);
-
- out:
- unmask_evtchn(evtchn);
- pirq_unmask_notify(irq_to_pirq(irq));
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-static void
-xenpic_pirq_enable_source(struct intsrc *isrc)
-{
- int evtchn;
- unsigned int irq;
-
- mtx_lock_spin(&irq_mapping_update_lock);
- irq = xenpic_vector(isrc);
- evtchn = evtchn_from_irq(irq);
-
- if (!VALID_EVTCHN(evtchn))
- goto done;
-
- unmask_evtchn(evtchn);
- pirq_unmask_notify(irq_to_pirq(irq));
- done:
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-static void
-xenpic_pirq_disable_source(struct intsrc *isrc, int eoi)
-{
- int evtchn;
- unsigned int irq;
-
- mtx_lock_spin(&irq_mapping_update_lock);
- irq = xenpic_vector(isrc);
- evtchn = evtchn_from_irq(irq);
-
- if (!VALID_EVTCHN(evtchn))
- goto done;
-
- mask_evtchn(evtchn);
- done:
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-
-static void
-xenpic_pirq_eoi_source(struct intsrc *isrc)
-{
- int evtchn;
- unsigned int irq;
-
- mtx_lock_spin(&irq_mapping_update_lock);
- irq = xenpic_vector(isrc);
- evtchn = evtchn_from_irq(irq);
-
- if (!VALID_EVTCHN(evtchn))
- goto done;
-
- unmask_evtchn(evtchn);
- pirq_unmask_notify(irq_to_pirq(irq));
- done:
- mtx_unlock_spin(&irq_mapping_update_lock);
-}
-
-int
-irq_to_evtchn_port(int irq)
-{
- return evtchn_from_irq(irq);
-}
-
-void
-mask_evtchn(int port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- synch_set_bit(port, &s->evtchn_mask[0]);
-}
-
-void
-unmask_evtchn(int port)
-{
- shared_info_t *s = HYPERVISOR_shared_info;
- unsigned int cpu = PCPU_GET(cpuid);
- vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];
-
- /* Slow path (hypercall) if this is a non-local port. */
- if (unlikely(cpu != cpu_from_evtchn(port))) {
- struct evtchn_unmask unmask = { .port = port };
- (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
- return;
- }
-
- synch_clear_bit(port, &s->evtchn_mask);
-
- /*
- * The following is basically the equivalent of 'hw_resend_irq'. Just
- * like a real IO-APIC we 'lose the interrupt edge' if the channel is
- * masked.
- */
- if (synch_test_bit(port, &s->evtchn_pending) &&
- !synch_test_and_set_bit(port / LONG_BIT,
- &vcpu_info->evtchn_pending_sel)) {
- vcpu_info->evtchn_upcall_pending = 1;
- if (!vcpu_info->evtchn_upcall_mask)
- force_evtchn_callback();
- }
-}
-
-void irq_resume(void)
-{
- evtchn_op_t op;
- int cpu, pirq, virq, ipi, irq, evtchn;
-
- struct evtchn_bind_virq bind_virq;
- struct evtchn_bind_ipi bind_ipi;
-
- init_evtchn_cpu_bindings();
-
- /* New event-channel space is not 'live' yet. */
- for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
- mask_evtchn(evtchn);
-
- /* Check that no PIRQs are still bound. */
- for (pirq = 0; pirq < NR_PIRQS; pirq++) {
- KASSERT(irq_info[pirq_to_irq(pirq)] == IRQ_UNBOUND,
- ("pirq_to_irq inconsistent"));
- }
-
- /* Secondary CPUs must have no VIRQ or IPI bindings. */
- for (cpu = 1; cpu < XEN_LEGACY_MAX_VCPUS; cpu++) {
- for (virq = 0; virq < NR_VIRQS; virq++) {
- KASSERT(pcpu_find(cpu)->pc_virq_to_irq[virq] == -1,
- ("virq_to_irq inconsistent"));
- }
- for (ipi = 0; ipi < NR_IPIS; ipi++) {
- KASSERT(pcpu_find(cpu)->pc_ipi_to_irq[ipi] == -1,
- ("ipi_to_irq inconsistent"));
- }
- }
-
- /* No IRQ <-> event-channel mappings. */
- for (irq = 0; irq < NR_IRQS; irq++)
- irq_info[irq] &= ~0xFFFF; /* zap event-channel binding */
- for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
- evtchn_to_irq[evtchn] = -1;
-
- /* Primary CPU: rebind VIRQs automatically. */
- for (virq = 0; virq < NR_VIRQS; virq++) {
- if ((irq = pcpu_find(0)->pc_virq_to_irq[virq]) == -1)
- continue;
-
- KASSERT(irq_info[irq] == mk_irq_info(IRQT_VIRQ, virq, 0),
- ("irq_info inconsistent"));
-
- /* Get a new binding from Xen. */
- bind_virq.virq = virq;
- bind_virq.vcpu = 0;
- HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind_virq);
- evtchn = bind_virq.port;
-
- /* Record the new mapping. */
- evtchn_to_irq[evtchn] = irq;
- irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
-
- /* Ready for use. */
- unmask_evtchn(evtchn);
- }
-
- /* Primary CPU: rebind IPIs automatically. */
- for (ipi = 0; ipi < NR_IPIS; ipi++) {
- if ((irq = pcpu_find(0)->pc_ipi_to_irq[ipi]) == -1)
- continue;
-
- KASSERT(irq_info[irq] == mk_irq_info(IRQT_IPI, ipi, 0),
- ("irq_info inconsistent"));
-
- /* Get a new binding from Xen. */
- memset(&op, 0, sizeof(op));
- bind_ipi.vcpu = 0;
- HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi);
- evtchn = bind_ipi.port;
-
- /* Record the new mapping. */
- evtchn_to_irq[evtchn] = irq;
- irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
-
- /* Ready for use. */
- unmask_evtchn(evtchn);
- }
-}
-
-static void
-evtchn_init(void *dummy __unused)
-{
- int i, cpu;
- struct xenpic_intsrc *pin, *tpin;
-
-
- init_evtchn_cpu_bindings();
-
- /* No VIRQ or IPI bindings. */
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
- for (i = 0; i < NR_VIRQS; i++)
- pcpu_find(cpu)->pc_virq_to_irq[i] = -1;
- for (i = 0; i < NR_IPIS; i++)
- pcpu_find(cpu)->pc_ipi_to_irq[i] = -1;
- }
-
- /* No event-channel -> IRQ mappings. */
- for (i = 0; i < NR_EVENT_CHANNELS; i++) {
- evtchn_to_irq[i] = -1;
- mask_evtchn(i); /* No event channels are 'live' right now. */
- }
-
- /* No IRQ -> event-channel mappings. */
- for (i = 0; i < NR_IRQS; i++)
- irq_info[i] = IRQ_UNBOUND;
-
- xp = malloc(sizeof(struct xenpic) + NR_IRQS*sizeof(struct xenpic_intsrc),
- M_DEVBUF, M_WAITOK);
-
- xp->xp_dynirq_pic = &xenpic_dynirq_template;
- xp->xp_pirq_pic = &xenpic_pirq_template;
- xp->xp_numintr = NR_IRQS;
- bzero(xp->xp_pins, sizeof(struct xenpic_intsrc) * NR_IRQS);
-
-
- /* We need to register our PIC's beforehand */
- if (intr_register_pic(&xenpic_pirq_template))
- panic("XEN: intr_register_pic() failure");
- if (intr_register_pic(&xenpic_dynirq_template))
- panic("XEN: intr_register_pic() failure");
-
- /*
- * Initialize the dynamic IRQ's - we initialize the structures, but
- * we do not bind them (bind_evtchn_to_irqhandle() does this)
- */
- pin = xp->xp_pins;
- for (i = 0; i < NR_DYNIRQS; i++) {
- /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
- irq_bindcount[dynirq_to_irq(i)] = 0;
-
- tpin = &pin[dynirq_to_irq(i)];
- tpin->xp_intsrc.is_pic = xp->xp_dynirq_pic;
- tpin->xp_vector = dynirq_to_irq(i);
-
- }
- /*
- * Now, we go ahead and claim every PIRQ there is.
- */
- pin = xp->xp_pins;
- for (i = 0; i < NR_PIRQS; i++) {
- /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
- irq_bindcount[pirq_to_irq(i)] = 0;
-
-#ifdef RTC_IRQ
- /* If not domain 0, force our RTC driver to fail its probe. */
- if ((i == RTC_IRQ) &&
- !(xen_start_info->flags & SIF_INITDOMAIN))
- continue;
-#endif
- tpin = &pin[pirq_to_irq(i)];
- tpin->xp_intsrc.is_pic = xp->xp_pirq_pic;
- tpin->xp_vector = pirq_to_irq(i);
-
- }
-}
-
-SYSINIT(evtchn_init, SI_SUB_INTR, SI_ORDER_MIDDLE, evtchn_init, NULL);
-
diff --git a/sys/xen/evtchn/evtchn_dev.c b/sys/xen/evtchn/evtchn_dev.c
index ab3bd17..9da2642 100644
--- a/sys/xen/evtchn/evtchn_dev.c
+++ b/sys/xen/evtchn/evtchn_dev.c
@@ -22,28 +22,23 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/ioccom.h>
+#include <sys/rman.h>
-#include <machine/xen/xen-os.h>
+#include <xen/xen-os.h>
+#include <xen/evtchn.h>
#include <xen/xen_intr.h>
+
#include <machine/bus.h>
-#include <sys/rman.h>
#include <machine/resource.h>
#include <machine/xen/synch_bitops.h>
-#include <xen/hypervisor.h>
-#include <xen/evtchn.h>
+#include <xen/evtchn/evtchnvar.h>
typedef struct evtchn_sotfc {
struct selinfo ev_rsel;
} evtchn_softc_t;
-
-#ifdef linuxcrap
-/* NB. This must be shared amongst drivers if more things go in /dev/xen */
-static devfs_handle_t xen_dev_dir;
-#endif
-
/* Only one process may open /dev/xen/evtchn at any time. */
static unsigned long evtchn_dev_inuse;
@@ -72,12 +67,12 @@ static d_close_t evtchn_close;
void
-evtchn_device_upcall(int port)
+evtchn_device_upcall(evtchn_port_t port)
{
mtx_lock(&upcall_lock);
- mask_evtchn(port);
- clear_evtchn(port);
+ evtchn_mask_port(port);
+ evtchn_clear_port(port);
if ( ring != NULL ) {
if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) {
@@ -208,7 +203,7 @@ evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
mtx_lock_spin(&lock);
for ( i = 0; i < (count/2); i++ )
if ( test_bit(kbuf[i], &bound_ports[0]) )
- unmask_evtchn(kbuf[i]);
+ evtchn_unmask_port(kbuf[i]);
mtx_unlock_spin(&lock);
rc = count;
@@ -224,6 +219,7 @@ evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
{
int rc = 0;
+#ifdef NOTYET
mtx_lock_spin(&lock);
switch ( cmd )
@@ -249,6 +245,7 @@ evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
}
mtx_unlock_spin(&lock);
+#endif
return rc;
}
@@ -309,7 +306,7 @@ evtchn_close(struct cdev *dev, int flag, int otyp, struct thread *td __unused)
mtx_lock_spin(&lock);
for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
if ( synch_test_and_clear_bit(i, &bound_ports[0]) )
- mask_evtchn(i);
+ evtchn_mask_port(i);
mtx_unlock_spin(&lock);
evtchn_dev_inuse = 0;
@@ -352,34 +349,6 @@ evtchn_dev_init(void *dummy __unused)
evtchn_dev->si_drv1 = malloc(sizeof(evtchn_softc_t), M_DEVBUF, M_WAITOK);
bzero(evtchn_dev->si_drv1, sizeof(evtchn_softc_t));
- /* XXX I don't think we need any of this rubbish */
-#if 0
- if ( err != 0 )
- {
- printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
- return err;
- }
-
- /* (DEVFS) create directory '/dev/xen'. */
- xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
-
- /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
- pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
- &link_dest[3],
- sizeof(link_dest) - 3);
- if ( pos >= 0 )
- strncpy(&link_dest[pos], "../", 3);
- /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
- (void)devfs_mk_symlink(xen_dev_dir,
- "evtchn",
- DEVFS_FL_DEFAULT,
- &link_dest[pos],
- &symlink_handle,
- NULL);
-
- /* (DEVFS) automatically destroy the symlink with its destination. */
- devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
-#endif
if (bootverbose)
printf("Event-channel device installed.\n");
@@ -387,5 +356,3 @@ evtchn_dev_init(void *dummy __unused)
}
SYSINIT(evtchn_dev_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_dev_init, NULL);
-
-
diff --git a/sys/xen/evtchn/evtchnvar.h b/sys/xen/evtchn/evtchnvar.h
new file mode 100644
index 0000000..8008d23
--- /dev/null
+++ b/sys/xen/evtchn/evtchnvar.h
@@ -0,0 +1,105 @@
+/******************************************************************************
+ * evtchn.h
+ *
+ * Data structures and definitions private to the FreeBSD implementation
+ * of the Xen event channel API.
+ *
+ * Copyright (c) 2004, K A Fraser
+ * Copyright (c) 2012, Spectra Logic Corporation
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __XEN_EVTCHN_EVTCHNVAR_H__
+#define __XEN_EVTCHN_EVTCHNVAR_H__
+
+#include <xen/hypervisor.h>
+#include <xen/interface/event_channel.h>
+
+enum evtchn_type {
+ EVTCHN_TYPE_UNBOUND,
+ EVTCHN_TYPE_PIRQ,
+ EVTCHN_TYPE_VIRQ,
+ EVTCHN_TYPE_IPI,
+ EVTCHN_TYPE_PORT,
+ EVTCHN_TYPE_COUNT
+};
+
+/** Submit a port notification for delivery to a userland evtchn consumer */
+void evtchn_device_upcall(evtchn_port_t port);
+
+/**
+ * Disable signal delivery for an event channel port, returning its
+ * previous mask state.
+ *
+ * \param port The event channel port to query and mask.
+ *
+ * \returns 1 if event delivery was previously disabled. Otherwise 0.
+ */
+static inline int
+evtchn_test_and_set_mask(evtchn_port_t port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ return synch_test_and_set_bit(port, s->evtchn_mask);
+}
+
+/**
+ * Clear any pending event for the given event channel port.
+ *
+ * \param port The event channel port to clear.
+ */
+static inline void
+evtchn_clear_port(evtchn_port_t port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ synch_clear_bit(port, &s->evtchn_pending[0]);
+}
+
+/**
+ * Disable signal delivery for an event channel port.
+ *
+ * \param port The event channel port to mask.
+ */
+static inline void
+evtchn_mask_port(evtchn_port_t port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+
+ synch_set_bit(port, &s->evtchn_mask[0]);
+}
+
+/**
+ * Enable signal delivery for an event channel port.
+ *
+ * \param port The event channel port to enable.
+ */
+static inline void
+evtchn_unmask_port(evtchn_port_t port)
+{
+ evtchn_unmask_t op = { .port = port };
+
+ HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &op);
+}
+
+#endif /* __XEN_EVTCHN_EVTCHNVAR_H__ */
diff --git a/sys/xen/features.c b/sys/xen/features.c
index f28fe04..bbb2896 100644
--- a/sys/xen/features.c
+++ b/sys/xen/features.c
@@ -4,7 +4,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <machine/xen/xen-os.h>
+#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <xen/features.h>
diff --git a/sys/xen/gnttab.c b/sys/xen/gnttab.c
index d8eb381..03c32b7 100644
--- a/sys/xen/gnttab.c
+++ b/sys/xen/gnttab.c
@@ -26,7 +26,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mman.h>
-#include <machine/xen/xen-os.h>
+#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <machine/xen/synch_bitops.h>
@@ -108,7 +108,7 @@ do_free_callbacks(void)
static inline void
check_free_callbacks(void)
{
- if (unlikely(gnttab_free_callback_list != NULL))
+ if (__predict_false(gnttab_free_callback_list != NULL))
do_free_callbacks();
}
@@ -136,7 +136,7 @@ gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly,
error = get_free_entries(1, &ref);
- if (unlikely(error))
+ if (__predict_false(error))
return (error);
shared[ref].frame = frame;
@@ -248,7 +248,7 @@ gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn,
int error, ref;
error = get_free_entries(1, &ref);
- if (unlikely(error))
+ if (__predict_false(error))
return (error);
gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
@@ -341,7 +341,7 @@ gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head)
int ref, error;
error = get_free_entries(count, &ref);
- if (unlikely(error))
+ if (__predict_false(error))
return (error);
*head = ref;
@@ -360,7 +360,7 @@ gnttab_claim_grant_reference(grant_ref_t *private_head)
{
grant_ref_t g = *private_head;
- if (unlikely(g == GNTTAB_LIST_END))
+ if (__predict_false(g == GNTTAB_LIST_END))
return (g);
*private_head = gnttab_entry(g);
return (g);
diff --git a/sys/xen/gnttab.h b/sys/xen/gnttab.h
index 1741ec3..d81e965 100644
--- a/sys/xen/gnttab.h
+++ b/sys/xen/gnttab.h
@@ -36,13 +36,12 @@
#ifndef __ASM_GNTTAB_H__
-#include <xen/interface/grant_table.h>
-
+#include <xen/xen-os.h>
#include <xen/hypervisor.h>
-#include <xen/interface/grant_table.h>
-#include <machine/xen/xen-os.h>
#include <xen/features.h>
+#include <xen/interface/grant_table.h>
+
#define GNTTAB_LIST_END GRANT_REF_INVALID
struct gnttab_free_callback {
diff --git a/sys/xen/hvm.h b/sys/xen/hvm.h
index 338a107..562aaf9 100644
--- a/sys/xen/hvm.h
+++ b/sys/xen/hvm.h
@@ -23,6 +23,9 @@
#ifndef __XEN_HVM_H__
#define __XEN_HVM_H__
+#include <xen/xen-os.h>
+#include <xen/hypervisor.h>
+
#include <xen/interface/hvm/params.h>
/**
@@ -91,4 +94,5 @@ enum {
void xen_hvm_set_callback(device_t);
void xen_hvm_suspend(void);
void xen_hvm_resume(void);
+void xen_hvm_init_cpu(void);
#endif /* __XEN_HVM_H__ */
diff --git a/sys/xen/interface/event_channel.h b/sys/xen/interface/event_channel.h
index 07ff321..65d1911 100644
--- a/sys/xen/interface/event_channel.h
+++ b/sys/xen/interface/event_channel.h
@@ -73,8 +73,11 @@
#define EVTCHNOP_reset 10
/* ` } */
+#ifndef __XEN_EVTCHN_PORT_DEFINED__
typedef uint32_t evtchn_port_t;
DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
+#define __XEN_EVTCHN_PORT_DEFINED__ 1
+#endif
/*
* EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
diff --git a/sys/xen/xen-os.h b/sys/xen/xen-os.h
new file mode 100644
index 0000000..95e8c6a
--- /dev/null
+++ b/sys/xen/xen-os.h
@@ -0,0 +1,95 @@
+/******************************************************************************
+ * xen/xen-os.h
+ *
+ * Random collection of macros and definition
+ *
+ * Copyright (c) 2003, 2004 Keir Fraser (on behalf of the Xen team)
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _XEN_XEN_OS_H_
+#define _XEN_XEN_OS_H_
+
+#if !defined(__XEN_INTERFACE_VERSION__)
+#define __XEN_INTERFACE_VERSION__ 0x00030208
+#endif
+
+#define GRANT_REF_INVALID 0xffffffff
+
+#ifdef LOCORE
+#define __ASSEMBLY__
+#endif
+
+#include <machine/xen/xen-os.h>
+
+#include <xen/interface/xen.h>
+
+/* Everything below this point is not included by assembler (.S) files. */
+#ifndef __ASSEMBLY__
+
+/* Force a proper event-channel callback from Xen. */
+void force_evtchn_callback(void);
+
+extern int gdtset;
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+enum xen_domain_type {
+ XEN_NATIVE, /* running on bare hardware */
+ XEN_PV_DOMAIN, /* running in a PV domain */
+ XEN_HVM_DOMAIN, /* running in a Xen hvm domain */
+};
+
+extern enum xen_domain_type xen_domain_type;
+
+static inline int
+xen_domain(void)
+{
+ return (xen_domain_type != XEN_NATIVE);
+}
+
+static inline int
+xen_pv_domain(void)
+{
+ return (xen_domain_type == XEN_PV_DOMAIN);
+}
+
+static inline int
+xen_hvm_domain(void)
+{
+ return (xen_domain_type == XEN_HVM_DOMAIN);
+}
+
+#ifndef xen_mb
+#define xen_mb() mb()
+#endif
+#ifndef xen_rmb
+#define xen_rmb() rmb()
+#endif
+#ifndef xen_wmb
+#define xen_wmb() wmb()
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _XEN_XEN_OS_H_ */
diff --git a/sys/xen/xen_intr.h b/sys/xen/xen_intr.h
index 2e753e6..109608f 100644
--- a/sys/xen/xen_intr.h
+++ b/sys/xen/xen_intr.h
@@ -1,103 +1,216 @@
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- */
+/******************************************************************************
+ * xen_intr.h
+ *
+ * APIs for managing Xen event channel, virtual IRQ, and physical IRQ
+ * notifications.
+ *
+ * Copyright (c) 2004, K A Fraser
+ * Copyright (c) 2012, Spectra Logic Corporation
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * $FreeBSD$
+ */
#ifndef _XEN_INTR_H_
#define _XEN_INTR_H_
-/*
-* The flat IRQ space is divided into two regions:
-* 1. A one-to-one mapping of real physical IRQs. This space is only used
-* if we have physical device-access privilege. This region is at the
-* start of the IRQ space so that existing device drivers do not need
-* to be modified to translate physical IRQ numbers into our IRQ space.
-* 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
-* are bound using the provided bind/unbind functions.
-*
-*
-* $FreeBSD$
-*/
-
-#define PIRQ_BASE 0
-#define NR_PIRQS 128
-
-#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS)
-#define NR_DYNIRQS 128
-
-#define NR_IRQS (NR_PIRQS + NR_DYNIRQS)
-
-#define pirq_to_irq(_x) ((_x) + PIRQ_BASE)
-#define irq_to_pirq(_x) ((_x) - PIRQ_BASE)
-
-#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE)
-#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
-
-/*
- * Dynamic binding of event channels and VIRQ sources to guest IRQ space.
+#ifndef __XEN_EVTCHN_PORT_DEFINED__
+typedef uint32_t evtchn_port_t;
+DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
+#define __XEN_EVTCHN_PORT_DEFINED__ 1
+#endif
+
+/** Registered Xen interrupt callback handle. */
+typedef void * xen_intr_handle_t;
+
+/** If non-zero, the hypervisor has been configured to use a direct vector */
+extern int xen_vector_callback_enabled;
+
+/**
+ * Associate an already allocated local event channel port an interrupt
+ * handler.
+ *
+ * \param dev The device making this bind request.
+ * \param local_port The event channel to bind.
+ * \param filter An interrupt filter handler. Specify NULL
+ * to always dispatch to the ithread handler.
+ * \param handler An interrupt ithread handler. Optional (can
+ * specify NULL) if all necessary event actions
+ * are performed by filter.
+ * \param arg Argument to present to both filter and handler.
+ * \param irqflags Interrupt handler flags. See sys/bus.h.
+ * \param handlep Pointer to an opaque handle used to manage this
+ * registration.
+ *
+ * \returns 0 on success, otherwise an errno.
*/
-
-/*
- * Bind a caller port event channel to an interrupt handler. If
- * successful, the guest IRQ number is returned in *irqp. Return zero
- * on success or errno otherwise.
+int xen_intr_bind_local_port(device_t dev, evtchn_port_t local_port,
+ driver_filter_t filter, driver_intr_t handler, void *arg,
+ enum intr_type irqflags, xen_intr_handle_t *handlep);
+
+/**
+ * Allocate a local event channel port, accessible by the specified
+ * remote/foreign domain and, if successful, associate the port with
+ * the specified interrupt handler.
+ *
+ * \param dev The device making this bind request.
+ * \param remote_domain Remote domain grant permission to signal the
+ * newly allocated local port.
+ * \param filter An interrupt filter handler. Specify NULL
+ * to always dispatch to the ithread handler.
+ * \param handler An interrupt ithread handler. Optional (can
+ * specify NULL) if all necessary event actions
+ * are performed by filter.
+ * \param arg Argument to present to both filter and handler.
+ * \param irqflags Interrupt handler flags. See sys/bus.h.
+ * \param handlep Pointer to an opaque handle used to manage this
+ * registration.
+ *
+ * \returns 0 on success, otherwise an errno.
*/
-extern int bind_caller_port_to_irqhandler(unsigned int caller_port,
- const char *devname, driver_intr_t handler, void *arg,
- unsigned long irqflags, unsigned int *irqp);
-
-/*
- * Bind a listening port to an interrupt handler. If successful, the
- * guest IRQ number is returned in *irqp. Return zero on success or
- * errno otherwise.
+int xen_intr_alloc_and_bind_local_port(device_t dev,
+ u_int remote_domain, driver_filter_t filter, driver_intr_t handler,
+ void *arg, enum intr_type irqflags, xen_intr_handle_t *handlep);
+
+/**
+ * Associate the specified interrupt handler with the remote event
+ * channel port specified by remote_domain and remote_port.
+ *
+ * \param dev The device making this bind request.
+ * \param remote_domain The domain peer for this event channel connection.
+ * \param remote_port Remote domain's local port number for this event
+ * channel port.
+ * \param filter An interrupt filter handler. Specify NULL
+ * to always dispatch to the ithread handler.
+ * \param handler An interrupt ithread handler. Optional (can
+ * specify NULL) if all necessary event actions
+ * are performed by filter.
+ * \param arg Argument to present to both filter and handler.
+ * \param irqflags Interrupt handler flags. See sys/bus.h.
+ * \param handlep Pointer to an opaque handle used to manage this
+ * registration.
+ *
+ * \returns 0 on success, otherwise an errno.
*/
-extern int bind_listening_port_to_irqhandler(unsigned int remote_domain,
- const char *devname, driver_intr_t handler, void *arg,
- unsigned long irqflags, unsigned int *irqp);
-
-/*
- * Bind a VIRQ to an interrupt handler. If successful, the guest IRQ
- * number is returned in *irqp. Return zero on success or errno
- * otherwise.
+int xen_intr_bind_remote_port(device_t dev, u_int remote_domain,
+ evtchn_port_t remote_port, driver_filter_t filter,
+ driver_intr_t handler, void *arg, enum intr_type irqflags,
+ xen_intr_handle_t *handlep);
+
+/**
+ * Associate the specified interrupt handler with the specified Xen
+ * virtual interrupt source.
+ *
+ * \param dev The device making this bind request.
+ * \param virq The Xen virtual IRQ number for the Xen interrupt
+ * source being hooked.
+ * \param cpu The cpu on which interrupt events should be delivered.
+ * \param filter An interrupt filter handler. Specify NULL
+ * to always dispatch to the ithread handler.
+ * \param handler An interrupt ithread handler. Optional (can
+ * specify NULL) if all necessary event actions
+ * are performed by filter.
+ * \param arg Argument to present to both filter and handler.
+ * \param irqflags Interrupt handler flags. See sys/bus.h.
+ * \param handlep Pointer to an opaque handle used to manage this
+ * registration.
+ *
+ * \returns 0 on success, otherwise an errno.
*/
-extern int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
- const char *devname, driver_filter_t filter, driver_intr_t handler,
- void *arg, unsigned long irqflags, unsigned int *irqp);
-
-/*
- * Bind an IPI to an interrupt handler. If successful, the guest
- * IRQ number is returned in *irqp. Return zero on success or errno
- * otherwise.
+int xen_intr_bind_virq(device_t dev, u_int virq, u_int cpu,
+ driver_filter_t filter, driver_intr_t handler,
+ void *arg, enum intr_type irqflags, xen_intr_handle_t *handlep);
+
+/**
+ * Associate an interprocessor interrupt vector with an interrupt handler.
+ *
+ * \param dev The device making this bind request.
+ * \param ipi The interprocessor interrupt vector number of the
+ * interrupt source being hooked.
+ * \param cpu The cpu receiving the IPI.
+ * \param filter An interrupt filter handler. Specify NULL
+ * to always dispatch to the ithread handler.
+ * \param irqflags Interrupt handler flags. See sys/bus.h.
+ * \param handlep Pointer to an opaque handle used to manage this
+ * registration.
+ *
+ * \returns 0 on success, otherwise an errno.
*/
-extern int bind_ipi_to_irqhandler(unsigned int ipi, unsigned int cpu,
- const char *devname, driver_filter_t filter,
- unsigned long irqflags, unsigned int *irqp);
-
-/*
- * Bind an interdomain event channel to an interrupt handler. If
- * successful, the guest IRQ number is returned in *irqp. Return zero
- * on success or errno otherwise.
+int xen_intr_bind_ipi(device_t dev, u_int ipi, u_int cpu,
+ driver_filter_t filter, enum intr_type irqflags,
+ xen_intr_handle_t *handlep);
+
+/**
+ * Unbind an interrupt handler from its interrupt source.
+ *
+ * \param handlep A pointer to the opaque handle that was initialized
+ * at the time the interrupt source was bound.
+ *
+ * \returns 0 on success, otherwise an errno.
+ *
+ * \note The event channel, if any, that was allocated at bind time is
+ * closed upon successful return of this method.
+ *
+ * \note It is always safe to call xen_intr_unbind() on a handle that
+ * has been initilized to NULL.
*/
-extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
- unsigned int remote_port, const char *devname,
- driver_intr_t handler, void *arg,
- unsigned long irqflags, unsigned int *irqp);
-
-/*
- * Unbind an interrupt handler using the guest IRQ number returned
- * when it was bound.
+void xen_intr_unbind(xen_intr_handle_t *handle);
+
+/**
+ * Add a description to an interrupt handler.
+ *
+ * \param handle The opaque handle that was initialized at the time
+ * the interrupt source was bound.
+ *
+ * \param fmt The sprintf compatible format string for the description,
+ * followed by optional sprintf arguments.
+ *
+ * \returns 0 on success, otherwise an errno.
*/
-extern void unbind_from_irqhandler(unsigned int irq);
-
-static __inline__ int irq_cannonicalize(unsigned int irq)
-{
- return (irq == 2) ? 9 : irq;
-}
-
-extern void disable_irq(unsigned int);
-extern void disable_irq_nosync(unsigned int);
-extern void enable_irq(unsigned int);
-
-extern void irq_suspend(void);
-extern void irq_resume(void);
-
-extern void idle_block(void);
-extern int ap_cpu_initclocks(int cpu);
+int
+xen_intr_describe(xen_intr_handle_t port_handle, const char *fmt, ...)
+ __attribute__((format(printf, 2, 3)));
+
+/**
+ * Signal the remote peer of an interrupt source associated with an
+ * event channel port.
+ *
+ * \param handle The opaque handle that was initialized at the time
+ * the interrupt source was bound.
+ *
+ * \note For xen interrupt sources other than event channel ports,
+ * this method takes no action.
+ */
+void xen_intr_signal(xen_intr_handle_t handle);
+
+/**
+ * Get the local event channel port number associated with this interrupt
+ * source.
+ *
+ * \param handle The opaque handle that was initialized at the time
+ * the interrupt source was bound.
+ *
+ * \returns 0 if the handle is invalid, otherwise positive port number.
+ */
+evtchn_port_t xen_intr_port(xen_intr_handle_t handle);
#endif /* _XEN_INTR_H_ */
diff --git a/sys/xen/xenbus/xenbus.c b/sys/xen/xenbus/xenbus.c
index 8887066..c59d4ae 100644
--- a/sys/xen/xenbus/xenbus.c
+++ b/sys/xen/xenbus/xenbus.c
@@ -50,11 +50,12 @@ __FBSDID("$FreeBSD$");
#include <sys/libkern.h>
#include <sys/sbuf.h>
-#include <machine/xen/xen-os.h>
+#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <xen/evtchn.h>
#include <xen/gnttab.h>
#include <xen/xenbus/xenbusvar.h>
+
#include <machine/stdarg.h>
MALLOC_DEFINE(M_XENBUS, "xenbus", "XenBus Support");
@@ -222,42 +223,6 @@ xenbus_grant_ring(device_t dev, unsigned long ring_mfn, grant_ref_t *refp)
return (0);
}
-int
-xenbus_alloc_evtchn(device_t dev, evtchn_port_t *port)
-{
- struct evtchn_alloc_unbound alloc_unbound;
- int err;
-
- alloc_unbound.dom = DOMID_SELF;
- alloc_unbound.remote_dom = xenbus_get_otherend_id(dev);
-
- err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
- &alloc_unbound);
-
- if (err) {
- xenbus_dev_fatal(dev, -err, "allocating event channel");
- return (-err);
- }
- *port = alloc_unbound.port;
- return (0);
-}
-
-int
-xenbus_free_evtchn(device_t dev, evtchn_port_t port)
-{
- struct evtchn_close close;
- int err;
-
- close.port = port;
-
- err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
- if (err) {
- xenbus_dev_error(dev, -err, "freeing event channel %d", port);
- return (-err);
- }
- return (0);
-}
-
XenbusState
xenbus_read_driver_state(const char *path)
{
diff --git a/sys/xen/xenbus/xenbus_if.m b/sys/xen/xenbus/xenbus_if.m
index 87d7c7f..fd9ae51 100644
--- a/sys/xen/xenbus/xenbus_if.m
+++ b/sys/xen/xenbus/xenbus_if.m
@@ -29,7 +29,8 @@
#include <sys/bus.h>
#include <machine/atomic.h>
-#include <machine/xen/xen-os.h>
+
+#include <xen/xen-os.h>
#include <xen/evtchn.h>
#include <xen/xenbus/xenbusvar.h>
diff --git a/sys/xen/xenbus/xenbusb_front.c b/sys/xen/xenbus/xenbusb_front.c
index 818e7f0..145d527 100644
--- a/sys/xen/xenbus/xenbusb_front.c
+++ b/sys/xen/xenbus/xenbusb_front.c
@@ -51,9 +51,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <sys/taskqueue.h>
-#include <machine/xen/xen-os.h>
#include <machine/stdarg.h>
+#include <xen/xen-os.h>
#include <xen/gnttab.h>
#include <xen/xenbus/xenbusvar.h>
#include <xen/xenbus/xenbusb.h>
diff --git a/sys/xen/xenbus/xenbusvar.h b/sys/xen/xenbus/xenbusvar.h
index 1c730fb..ab5d01f 100644
--- a/sys/xen/xenbus/xenbusvar.h
+++ b/sys/xen/xenbus/xenbusvar.h
@@ -43,8 +43,8 @@
#include <sys/sbuf.h>
#include <machine/stdarg.h>
-#include <machine/xen/xen-os.h>
+#include <xen/xen-os.h>
#include <xen/interface/grant_table.h>
#include <xen/interface/io/xenbus.h>
#include <xen/interface/io/xs_wire.h>
@@ -195,39 +195,6 @@ int xenbus_watch_path2(device_t dev, const char *path,
int xenbus_grant_ring(device_t dev, unsigned long ring_mfn, grant_ref_t *refp);
/**
- * Allocate an event channel for the given XenBus device.
- *
- * \param dev The device for which to allocate the event channel.
- * \param port[out] The port identifier for the allocated event channel.
- *
- * \return On success, 0. Otherwise an errno value indicating the
- * type of failure.
- *
- * A successfully allocated event channel should be free'd using
- * xenbus_free_evtchn().
- *
- * \note On error, \a dev will be switched to the XenbusStateClosing
- * state and the returned error is saved in the per-device error node
- * for \a dev in the XenStore.
- */
-int xenbus_alloc_evtchn(device_t dev, evtchn_port_t *port);
-
-/**
- * Free an existing event channel.
- *
- * \param dev The device which allocated this event channel.
- * \param port The port identifier for the event channel to free.
- *
- * \return On success, 0. Otherwise an errno value indicating the
- * type of failure.
- *
- * \note On error, \a dev will be switched to the XenbusStateClosing
- * state and the returned error is saved in the per-device error node
- * for \a dev in the XenStore.
- */
-int xenbus_free_evtchn(device_t dev, evtchn_port_t port);
-
-/**
* Record the given errno, along with the given, printf-style, formatted
* message in dev's device specific error node in the XenStore.
*
diff --git a/sys/xen/xenstore/xenstore.c b/sys/xen/xenstore/xenstore.c
index a07a262..d404862 100644
--- a/sys/xen/xenstore/xenstore.c
+++ b/sys/xen/xenstore/xenstore.c
@@ -49,10 +49,9 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <sys/unistd.h>
-#include <machine/xen/xen-os.h>
#include <machine/stdarg.h>
-#include <xen/evtchn.h>
+#include <xen/xen-os.h>
#include <xen/gnttab.h>
#include <xen/hypervisor.h>
#include <xen/xen_intr.h>
@@ -244,8 +243,8 @@ struct xs_softc {
*/
int evtchn;
- /** Interrupt number for our event channel. */
- u_int irq;
+ /** Handle for XenStore interrupts. */
+ xen_intr_handle_t xen_intr_handle;
/**
* Interrupt driven config hook allowing us to defer
@@ -505,11 +504,10 @@ xs_write_store(const void *tdata, unsigned len)
xen_store->req_prod += avail;
/*
- * notify_remote_via_evtchn implies mb(). The other side
- * will see the change to req_prod at the time of the
- * interrupt.
+ * xen_intr_signal() implies mb(). The other side will see
+ * the change to req_prod at the time of the interrupt.
*/
- notify_remote_via_evtchn(xs.evtchn);
+ xen_intr_signal(xs.xen_intr_handle);
}
return (0);
@@ -597,11 +595,10 @@ xs_read_store(void *tdata, unsigned len)
xen_store->rsp_cons += avail;
/*
- * notify_remote_via_evtchn implies mb(). The producer
- * will see the updated consumer index when the event
- * is delivered.
+ * xen_intr_signal() implies mb(). The producer will see
+ * the updated consumer index when the event is delivered.
*/
- notify_remote_via_evtchn(xs.evtchn);
+ xen_intr_signal(xs.xen_intr_handle);
}
return (0);
@@ -1068,11 +1065,11 @@ xs_init_comms(void)
xen_store->rsp_cons = xen_store->rsp_prod;
}
- if (xs.irq)
- unbind_from_irqhandler(xs.irq);
+ xen_intr_unbind(&xs.xen_intr_handle);
- error = bind_caller_port_to_irqhandler(xs.evtchn, "xenstore",
- xs_intr, NULL, INTR_TYPE_NET, &xs.irq);
+ error = xen_intr_bind_local_port(xs.xs_dev, xs.evtchn,
+ /*filter*/NULL, xs_intr, /*arg*/NULL, INTR_TYPE_NET|INTR_MPSAFE,
+ &xs.xen_intr_handle);
if (error) {
log(LOG_WARNING, "XENSTORE request irq failed %i\n", error);
return (error);
@@ -1168,7 +1165,6 @@ xs_attach(device_t dev)
sx_init(&xs.suspend_mutex, "xenstore suspend");
mtx_init(&xs.registered_watches_lock, "watches", NULL, MTX_DEF);
mtx_init(&xs.watch_events_lock, "watch events", NULL, MTX_DEF);
- xs.irq = 0;
/* Initialize the shared memory rings to talk to xenstored */
error = xs_init_comms();
diff --git a/sys/xen/xenstore/xenstore_dev.c b/sys/xen/xenstore/xenstore_dev.c
index 1fa4197..e1b40914 100644
--- a/sys/xen/xenstore/xenstore_dev.c
+++ b/sys/xen/xenstore/xenstore_dev.c
@@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/conf.h>
-#include <machine/xen/xen-os.h>
+#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <xen/xenstore/xenstorevar.h>
diff --git a/sys/xen/xenstore/xenstorevar.h b/sys/xen/xenstore/xenstorevar.h
index 4a1382d..208e5bf 100644
--- a/sys/xen/xenstore/xenstorevar.h
+++ b/sys/xen/xenstore/xenstorevar.h
@@ -41,8 +41,8 @@
#include <sys/sbuf.h>
#include <machine/stdarg.h>
-#include <machine/xen/xen-os.h>
+#include <xen/xen-os.h>
#include <xen/interface/grant_table.h>
#include <xen/interface/io/xenbus.h>
#include <xen/interface/io/xs_wire.h>
OpenPOWER on IntegriCloud