svn commit: r184015 - in projects/release_6_3_xen/sys/xen: . evtchn interface interface/arch-x86 interface/arch-x86/hvm interface/foreign interface/hvm interface/io xenbus

Kip Macy kmacy at FreeBSD.org
Sat Oct 18 06:19:13 UTC 2008


Author: kmacy
Date: Sat Oct 18 06:19:12 2008
New Revision: 184015
URL: http://svn.freebsd.org/changeset/base/184015

Log:
  merge xen includes

Added:
  projects/release_6_3_xen/sys/xen/
  projects/release_6_3_xen/sys/xen/evtchn/
  projects/release_6_3_xen/sys/xen/evtchn/evtchn.c
  projects/release_6_3_xen/sys/xen/evtchn/evtchn_dev.c
  projects/release_6_3_xen/sys/xen/features.c
  projects/release_6_3_xen/sys/xen/gnttab.c
  projects/release_6_3_xen/sys/xen/gnttab.h
  projects/release_6_3_xen/sys/xen/interface/   (props changed)
  projects/release_6_3_xen/sys/xen/interface/COPYING
  projects/release_6_3_xen/sys/xen/interface/acm.h
  projects/release_6_3_xen/sys/xen/interface/acm_ops.h
  projects/release_6_3_xen/sys/xen/interface/arch-ia64.h
  projects/release_6_3_xen/sys/xen/interface/arch-powerpc.h
  projects/release_6_3_xen/sys/xen/interface/arch-x86/   (props changed)
  projects/release_6_3_xen/sys/xen/interface/arch-x86/cpuid.h
  projects/release_6_3_xen/sys/xen/interface/arch-x86/hvm/
  projects/release_6_3_xen/sys/xen/interface/arch-x86/hvm/save.h
  projects/release_6_3_xen/sys/xen/interface/arch-x86/xen-mca.h
  projects/release_6_3_xen/sys/xen/interface/arch-x86/xen-x86_32.h
  projects/release_6_3_xen/sys/xen/interface/arch-x86/xen-x86_64.h
  projects/release_6_3_xen/sys/xen/interface/arch-x86/xen.h
  projects/release_6_3_xen/sys/xen/interface/arch-x86_32.h
  projects/release_6_3_xen/sys/xen/interface/arch-x86_64.h
  projects/release_6_3_xen/sys/xen/interface/callback.h
  projects/release_6_3_xen/sys/xen/interface/dom0_ops.h
  projects/release_6_3_xen/sys/xen/interface/domctl.h
  projects/release_6_3_xen/sys/xen/interface/elfnote.h
  projects/release_6_3_xen/sys/xen/interface/elfstructs.h
  projects/release_6_3_xen/sys/xen/interface/event_channel.h
  projects/release_6_3_xen/sys/xen/interface/features.h
  projects/release_6_3_xen/sys/xen/interface/foreign/   (props changed)
  projects/release_6_3_xen/sys/xen/interface/foreign/Makefile
  projects/release_6_3_xen/sys/xen/interface/foreign/mkchecker.py
  projects/release_6_3_xen/sys/xen/interface/foreign/mkheader.py
  projects/release_6_3_xen/sys/xen/interface/foreign/reference.size
  projects/release_6_3_xen/sys/xen/interface/foreign/structs.py
  projects/release_6_3_xen/sys/xen/interface/grant_table.h
  projects/release_6_3_xen/sys/xen/interface/hvm/   (props changed)
  projects/release_6_3_xen/sys/xen/interface/hvm/e820.h
  projects/release_6_3_xen/sys/xen/interface/hvm/hvm_info_table.h
  projects/release_6_3_xen/sys/xen/interface/hvm/hvm_op.h
  projects/release_6_3_xen/sys/xen/interface/hvm/ioreq.h
  projects/release_6_3_xen/sys/xen/interface/hvm/params.h
  projects/release_6_3_xen/sys/xen/interface/hvm/save.h
  projects/release_6_3_xen/sys/xen/interface/hvm/vmx_assist.h
  projects/release_6_3_xen/sys/xen/interface/io/   (props changed)
  projects/release_6_3_xen/sys/xen/interface/io/blkif.h
  projects/release_6_3_xen/sys/xen/interface/io/console.h
  projects/release_6_3_xen/sys/xen/interface/io/fbif.h
  projects/release_6_3_xen/sys/xen/interface/io/kbdif.h
  projects/release_6_3_xen/sys/xen/interface/io/netif.h
  projects/release_6_3_xen/sys/xen/interface/io/pciif.h
  projects/release_6_3_xen/sys/xen/interface/io/protocols.h
  projects/release_6_3_xen/sys/xen/interface/io/ring.h
  projects/release_6_3_xen/sys/xen/interface/io/tpmif.h
  projects/release_6_3_xen/sys/xen/interface/io/xenbus.h
  projects/release_6_3_xen/sys/xen/interface/io/xs_wire.h
  projects/release_6_3_xen/sys/xen/interface/kexec.h
  projects/release_6_3_xen/sys/xen/interface/libelf.h
  projects/release_6_3_xen/sys/xen/interface/memory.h
  projects/release_6_3_xen/sys/xen/interface/nmi.h
  projects/release_6_3_xen/sys/xen/interface/physdev.h
  projects/release_6_3_xen/sys/xen/interface/platform.h
  projects/release_6_3_xen/sys/xen/interface/sched.h
  projects/release_6_3_xen/sys/xen/interface/sysctl.h
  projects/release_6_3_xen/sys/xen/interface/trace.h
  projects/release_6_3_xen/sys/xen/interface/vcpu.h
  projects/release_6_3_xen/sys/xen/interface/version.h
  projects/release_6_3_xen/sys/xen/interface/xen-compat.h
  projects/release_6_3_xen/sys/xen/interface/xen.h
  projects/release_6_3_xen/sys/xen/interface/xencomm.h
  projects/release_6_3_xen/sys/xen/interface/xenoprof.h
  projects/release_6_3_xen/sys/xen/xenbus/
  projects/release_6_3_xen/sys/xen/xenbus/init.txt
  projects/release_6_3_xen/sys/xen/xenbus/xenbus_client.c
  projects/release_6_3_xen/sys/xen/xenbus/xenbus_comms.c
  projects/release_6_3_xen/sys/xen/xenbus/xenbus_comms.h
  projects/release_6_3_xen/sys/xen/xenbus/xenbus_dev.c
  projects/release_6_3_xen/sys/xen/xenbus/xenbus_probe.c
  projects/release_6_3_xen/sys/xen/xenbus/xenbus_probe_backend.c
  projects/release_6_3_xen/sys/xen/xenbus/xenbus_xs.c

Added: projects/release_6_3_xen/sys/xen/evtchn/evtchn.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/release_6_3_xen/sys/xen/evtchn/evtchn.c	Sat Oct 18 06:19:12 2008	(r184015)
@@ -0,0 +1,1115 @@
+/******************************************************************************
+ * 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/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/interrupt.h>
+
+#include <machine/cpufunc.h>
+#include <machine/intr_machdep.h>
+#include <machine/xen/xen-os.h>
+#include <machine/xen/xen_intr.h>
+#include <machine/xen/synch_bitops.h>
+#include <machine/xen/evtchn.h>
+#include <machine/xen/hypervisor.h>
+
+
+
+/* linux helper functions that got sucked in 
+ * rename and move XXX
+ */
+
+
+static inline int find_first_bit(const unsigned long *addr, unsigned size)
+{
+	int d0, d1;
+	int res;
+
+	/* This looks at memory. Mark it volatile to tell gcc not to move it around */
+	__asm__ __volatile__(
+		"xorl %%eax,%%eax\n\t"
+		"repe; scasl\n\t"
+		"jz 1f\n\t"
+		"leal -4(%%edi),%%edi\n\t"
+		"bsfl (%%edi),%%eax\n"
+		"1:\tsubl %%ebx,%%edi\n\t"
+		"shll $3,%%edi\n\t"
+		"addl %%edi,%%eax"
+		:"=a" (res), "=&c" (d0), "=&D" (d1)
+		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory");
+	return res;
+}
+
+#define min_t(type,x,y) \
+	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+#define first_cpu(src) __first_cpu(&(src), NR_CPUS)
+static inline int __first_cpu(const xen_cpumask_t *srcp, int nbits)
+{
+	return min_t(int, nbits, find_first_bit(srcp->bits, nbits));
+}
+
+static inline unsigned long __ffs(unsigned long word)
+{
+        __asm__("bsfl %1,%0"
+                :"=r" (word)
+                :"rm" (word));
+        return word;
+}
+
+static struct mtx irq_mapping_update_lock;
+static struct xenpic *xp;
+struct xenpic_intsrc {
+	struct intsrc     xp_intsrc;
+	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
+};
+
+/* Constructor for packed IRQ information. */
+#define mk_irq_info(type, index, evtchn)				\
+	(((uint32_t)(type) << 24) | ((uint32_t)(index) << 16) | (uint32_t)(evtchn))
+/* Convenient shorthand for packed representation of an unbound IRQ. */
+#define IRQ_UNBOUND	mk_irq_info(IRQT_UNBOUND, 0, 0)
+/* Accessor macros for packed IRQ information. */
+#define evtchn_from_irq(irq) ((uint16_t)(irq_info[irq]))
+#define index_from_irq(irq)  ((uint8_t)(irq_info[irq] >> 16))
+#define type_from_irq(irq)   ((uint8_t)(irq_info[irq] >> 24))
+
+/* IRQ <-> VIRQ mapping. */ 
+DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1}; 
+ 
+/* IRQ <-> IPI mapping. */ 
+#ifndef NR_IPIS 
+#define NR_IPIS 1 
+#endif 
+DEFINE_PER_CPU(int, ipi_to_irq[NR_IPIS]) = {[0 ... NR_IPIS-1] = -1}; 
+
+/* 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 CONFIG_SMP
+
+static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
+
+#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 = smp_processor_id();
+	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 * BITS_PER_LONG) + 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);
+			}
+		}
+	}
+}
+
+void
+ipi_pcpu(unsigned int cpu, int vector) 
+{ 
+        int irq = per_cpu(ipi_to_irq, cpu)[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 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]++;
+
+ out:
+        mtx_unlock_spin(&irq_mapping_update_lock);
+        return irq;
+}
+
+static int
+bind_local_port_to_irq(unsigned int local_port)
+{
+        int irq;
+
+        mtx_lock_spin(&irq_mapping_update_lock);
+
+        PANIC_IF(evtchn_to_irq[local_port] != -1);
+
+        if ((irq = find_unbound_irq()) < 0) {
+                struct evtchn_close close = { .port = local_port };
+                PANIC_IF(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]++;
+
+ out:
+        mtx_unlock_spin(&irq_mapping_update_lock);
+        return irq;
+}
+
+static int
+bind_listening_port_to_irq(unsigned int remote_domain)
+{
+        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);
+}
+
+static int
+bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
+    unsigned int remote_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);
+}
+
+static int 
+bind_virq_to_irq(unsigned int virq, unsigned int cpu)
+{
+	struct evtchn_bind_virq bind_virq;
+	int evtchn, irq;
+
+	mtx_lock_spin(&irq_mapping_update_lock);
+
+	if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
+		bind_virq.virq = virq;
+		bind_virq.vcpu = cpu;
+		PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+			&bind_virq) != 0);
+
+		evtchn = bind_virq.port;
+
+		irq = find_unbound_irq();
+		evtchn_to_irq[evtchn] = irq;
+		irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn);
+
+		per_cpu(virq_to_irq, cpu)[virq] = irq;
+
+		bind_evtchn_to_cpu(evtchn, cpu);
+	}
+
+	irq_bindcount[irq]++;
+
+	mtx_unlock_spin(&irq_mapping_update_lock);
+
+	return irq;
+}
+
+static int 
+bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
+{
+	struct evtchn_bind_ipi bind_ipi;
+	int evtchn, irq;
+	
+	mtx_lock_spin(&irq_mapping_update_lock);
+	
+	if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) {
+		if ((irq = find_unbound_irq()) < 0)
+			goto out;
+
+		bind_ipi.vcpu = cpu;
+		PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi) != 0);
+		evtchn = bind_ipi.port;
+
+		irq = find_unbound_irq();
+		evtchn_to_irq[evtchn] = irq;
+		irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn);
+
+		per_cpu(ipi_to_irq, cpu)[ipi] = irq;
+
+		bind_evtchn_to_cpu(evtchn, cpu);
+	}
+
+	irq_bindcount[irq]++;
+out:
+	
+	mtx_unlock_spin(&irq_mapping_update_lock);
+
+	return irq;
+}
+
+
+void 
+unbind_from_irq(int irq)
+{
+	struct evtchn_close close;
+	int evtchn = evtchn_from_irq(irq);
+
+	mtx_lock_spin(&irq_mapping_update_lock);
+
+	if ((--irq_bindcount[irq] == 0) && VALID_EVTCHN(evtchn)) {
+		close.port = evtchn;
+		PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0);
+
+		switch (type_from_irq(irq)) {
+		case IRQT_VIRQ:
+			per_cpu(virq_to_irq, cpu_from_evtchn(evtchn))[index_from_irq(irq)] = -1;
+			break;
+		case IRQT_IPI:
+			per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn))[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,
+                          void **cookiep)
+{
+	unsigned int irq;
+	int retval;
+
+	irq = bind_caller_port_to_irq(caller_port);
+	intr_register_source(&xp->xp_pins[irq].xp_intsrc);
+	retval = intr_add_handler(devname, irq, NULL, handler, arg, irqflags, cookiep);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return -retval;
+	}
+
+	return irq;
+}
+
+int 
+bind_listening_port_to_irqhandler(
+	                  unsigned int remote_domain,
+			  const char *devname,
+			  driver_intr_t handler,
+			  void *arg,
+			  unsigned long irqflags,
+                          void **cookiep)
+{
+	unsigned int irq;
+	int retval;
+
+	irq = bind_listening_port_to_irq(remote_domain);
+	intr_register_source(&xp->xp_pins[irq].xp_intsrc);
+	retval = intr_add_handler(devname, irq, NULL, handler, arg, irqflags, cookiep);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return -retval;
+	}
+
+	return irq;
+}
+
+int 
+bind_interdomain_evtchn_to_irqhandler(
+	                unsigned int remote_domain,
+	                unsigned int remote_port,
+			const char *devname,
+			driver_filter_t filter,
+			driver_intr_t handler,
+			unsigned long irqflags)
+{
+	unsigned int irq;
+	int retval;
+
+	irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port);
+	intr_register_source(&xp->xp_pins[irq].xp_intsrc);
+	retval = intr_add_handler(devname, irq, filter, handler, NULL, irqflags, NULL);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return -retval;
+	}
+
+	return irq;
+}
+
+int 
+bind_virq_to_irqhandler(unsigned int virq,
+			unsigned int cpu,
+			const char *devname,
+			driver_filter_t filter,
+			driver_intr_t handler,
+			unsigned long irqflags)
+{
+	unsigned int irq;
+	int retval;
+
+	irq = bind_virq_to_irq(virq, cpu);
+	intr_register_source(&xp->xp_pins[irq].xp_intsrc);
+	retval = intr_add_handler(devname, irq, filter, handler, NULL, irqflags, NULL);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return -retval;
+	}
+
+	return irq;
+}
+
+int 
+bind_ipi_to_irqhandler(unsigned int ipi,
+		       unsigned int cpu,
+		       const char *devname,
+		       driver_intr_t handler,
+		       unsigned long irqflags)
+{
+	unsigned int irq;
+	int retval;
+
+	irq = bind_ipi_to_irq(ipi, cpu);
+	intr_register_source(&xp->xp_pins[irq].xp_intsrc);
+	retval = intr_add_handler(devname, irq, NULL, handler, NULL, irqflags, NULL);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return -retval;
+	}
+
+	return irq;
+}
+
+void
+unbind_from_irqhandler(unsigned int irq, void *dev_id)
+{
+	if (dev_id)
+		intr_remove_handler(dev_id); /* XXX */
+	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, xen_cpumask_t dest)
+{
+	unsigned tcpu = first_cpu(dest);
+	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 void     xenpic_pirq_disable_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 void     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_disable_intr	=	xenpic_pirq_disable_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);
+	xp->xp_masked = 1;
+	irq = xenpic_vector(isrc);
+	mask_evtchn(evtchn_from_irq(irq));
+	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 void 
+xenpic_assign_cpu(struct intsrc *isrc, u_int apic_id)
+{ 
+	TODO; 
+}
+
+void
+notify_remote_via_irq(int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		notify_remote_via_evtchn(evtchn);
+}
+
+/* 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) {
+		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_disable_intr(struct intsrc *isrc)
+{
+	unsigned int irq;
+	int evtchn;
+	struct evtchn_close close;
+			
+	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);
+
+	close.port = evtchn;
+	PANIC_IF(HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0);
+
+	bind_evtchn_to_cpu(evtchn, 0);
+	evtchn_to_irq[evtchn] = -1;
+	irq_info[irq] = IRQ_UNBOUND;
+ done:
+	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 = smp_processor_id();
+	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 / BITS_PER_LONG,
+				    &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++)
+		PANIC_IF(irq_info[pirq_to_irq(pirq)] != IRQ_UNBOUND);
+
+	/* Secondary CPUs must have no VIRQ or IPI bindings. */
+	for (cpu = 1; cpu < NR_CPUS; cpu++) {
+		for (virq = 0; virq < NR_VIRQS; virq++)
+			PANIC_IF(per_cpu(virq_to_irq, cpu)[virq] != -1);
+		for (ipi = 0; ipi < NR_IPIS; ipi++)
+			PANIC_IF(per_cpu(ipi_to_irq, cpu)[ipi] != -1);
+	}
+
+	/* 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 = per_cpu(virq_to_irq, 0)[virq]) == -1)
+			continue;
+
+		PANIC_IF(irq_info[irq] != mk_irq_info(IRQT_VIRQ, virq, 0));
+
+		/* Get a new binding from Xen. */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list