#include <vm/pmap.h>
#include <machine/intr_machdep.h>
-#include <x86/apicvar.h>
-#include <x86/apicreg.h>
#include <machine/smp.h>
#include <machine/stdarg.h>
#include <xen/xen_intr.h>
#include <xen/evtchn/evtchnvar.h>
-#include <dev/xen/xenpci/xenpcivar.h>
#include <dev/pci/pcivar.h>
#ifdef DDB
#define is_valid_evtchn(x) ((x) != XEN_INVALID_EVTCHN)
struct xenisrc {
- struct intsrc xi_intsrc;
+ struct intr_event *xi_event;
enum evtchn_type xi_type;
int xi_cpu; /* VCPU for delivery. */
- int xi_vector; /* Global isrc vector number. */
evtchn_port_t xi_port;
int xi_pirq;
int xi_virq;
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
-static void xen_intr_suspend(struct pic *);
-static void xen_intr_resume(struct pic *, bool suspend_cancelled);
-static void xen_intr_enable_source(struct intsrc *isrc);
-static void xen_intr_disable_source(struct intsrc *isrc, int eoi);
-static void xen_intr_eoi_source(struct intsrc *isrc);
-static void xen_intr_enable_intr(struct intsrc *isrc);
-static void xen_intr_disable_intr(struct intsrc *isrc);
-static int xen_intr_vector(struct intsrc *isrc);
-static int xen_intr_source_pending(struct intsrc *isrc);
-static int xen_intr_config_intr(struct intsrc *isrc,
- enum intr_trigger trig, enum intr_polarity pol);
-static int xen_intr_assign_cpu(struct intsrc *isrc, u_int to_cpu);
-static int xen_pic_assign_cpu(struct intsrc *isrc, u_int apic_id);
-
-static void xen_intr_pirq_enable_source(struct intsrc *isrc);
-static void xen_intr_pirq_disable_source(struct intsrc *isrc, int eoi);
-static void xen_intr_pirq_eoi_source(struct intsrc *isrc);
-static void xen_intr_pirq_enable_intr(struct intsrc *isrc);
-static void xen_intr_pirq_disable_intr(struct intsrc *isrc);
-static int xen_intr_pirq_config_intr(struct intsrc *isrc,
- enum intr_trigger trig, enum intr_polarity pol);
+static void xen_intr_enable_intr(void *arg);
+static void xen_intr_disable_intr(void *arg);
-/**
- * PIC interface for all event channel port types except physical IRQs.
- */
-struct pic xen_intr_pic = {
- .pic_enable_source = xen_intr_enable_source,
- .pic_disable_source = xen_intr_disable_source,
- .pic_eoi_source = xen_intr_eoi_source,
- .pic_enable_intr = xen_intr_enable_intr,
- .pic_disable_intr = xen_intr_disable_intr,
- .pic_vector = xen_intr_vector,
- .pic_source_pending = xen_intr_source_pending,
- .pic_suspend = xen_intr_suspend,
- .pic_resume = xen_intr_resume,
- .pic_config_intr = xen_intr_config_intr,
- .pic_assign_cpu = xen_pic_assign_cpu
-};
-
-/**
- * PIC interface for all event channel representing
- * physical interrupt sources.
- */
-struct pic xen_intr_pirq_pic = {
- .pic_enable_source = xen_intr_pirq_enable_source,
- .pic_disable_source = xen_intr_pirq_disable_source,
- .pic_eoi_source = xen_intr_pirq_eoi_source,
- .pic_enable_intr = xen_intr_pirq_enable_intr,
- .pic_disable_intr = xen_intr_pirq_disable_intr,
- .pic_vector = xen_intr_vector,
- .pic_source_pending = xen_intr_source_pending,
- .pic_config_intr = xen_intr_pirq_config_intr,
- .pic_assign_cpu = xen_pic_assign_cpu
-};
+static int xen_intr_assign_cpu(struct xenisrc *isrc, u_int to_cpu);
static struct mtx xen_intr_isrc_lock;
static int xen_intr_auto_vector_count;
char buf[MAXCOMLEN + 1];
struct xen_intr_pcpu_data *pcpu;
+ static u_long count = 0;
+
pcpu = DPCPU_ID_PTR(cpu, xen_intr_pcpu);
if (pcpu->evtchn_intrcnt != NULL)
return;
snprintf(buf, sizeof(buf), "cpu%d:xen", cpu);
- intrcnt_add(buf, &pcpu->evtchn_intrcnt);
+
+ /* TODO: handle correctly IRQ counter */
+ pcpu->evtchn_intrcnt = &count;
}
/**
static struct xenisrc *
xen_intr_find_unused_isrc(enum evtchn_type type)
{
+#if 0
int isrc_idx;
KASSERT(mtx_owned(&xen_intr_isrc_lock), ("Evtchn isrc lock not held"));
return (isrc);
}
}
+#endif
return (NULL);
}
{
static int warned;
struct xenisrc *isrc;
+ int error;
KASSERT(mtx_owned(&xen_intr_isrc_lock), ("Evtchn alloc lock not held"));
xen_intr_auto_vector_count++;
}
- KASSERT((intr_lookup_source(vector) == NULL),
- ("Trying to use an already allocated vector"));
-
mtx_unlock(&xen_intr_isrc_lock);
isrc = malloc(sizeof(*isrc), M_XENINTR, M_WAITOK | M_ZERO);
- isrc->xi_intsrc.is_pic =
- (type == EVTCHN_TYPE_PIRQ) ? &xen_intr_pirq_pic : &xen_intr_pic;
- isrc->xi_vector = vector;
isrc->xi_type = type;
- intr_register_source(&isrc->xi_intsrc);
+ /* TODO: Make the name of the event more accurate */
+ error = intr_event_create(&isrc->xi_event, isrc, 0, vector /* IRQ */,
+ xen_intr_disable_intr /* mask */,
+ xen_intr_enable_intr /* unmask */,
+ NULL /* EOI */,
+ NULL /* cpu assign */, "xen%d:", vector);
mtx_lock(&xen_intr_isrc_lock);
+ if (error) {
+ printf("%s: event creation failed (%d)\n",
+ __FUNCTION__, error);
+ free(isrc, M_XENINTR);
+ isrc = NULL;
+ }
+
return (isrc);
}
{
mtx_lock(&xen_intr_isrc_lock);
- if (isrc->xi_intsrc.is_handlers != 0) {
+
+ if (!TAILQ_EMPTY(&isrc->xi_event->ie_handlers)) {
mtx_unlock(&xen_intr_isrc_lock);
return (EBUSY);
}
evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
evtchn_cpu_unmask_port(0, isrc->xi_port);
+ intr_event_destroy(isrc->xi_event);
+
if (isrc->xi_close != 0 && is_valid_evtchn(isrc->xi_port)) {
struct evtchn_close close = { .port = isrc->xi_port };
if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))
xen_intr_handle_upcall(struct trapframe *trap_frame)
{
u_int l1i, l2i, port, cpu;
- u_long masked_l1, masked_l2;
+ xen_ulong_t masked_l1, masked_l2;
struct xenisrc *isrc;
shared_info_t *s;
vcpu_info_t *v;
struct xen_intr_pcpu_data *pc;
- u_long l1, l2;
+ xen_ulong_t l1, l2;
+ int error;
/*
* Disable preemption in order to always check and fire events
v->evtchn_upcall_pending = 0;
-#if 0
-#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
- /* Clear master flag /before/ clearing selector flag. */
- wmb();
-#endif
-#endif
-
- l1 = atomic_readandclear_long(&v->evtchn_pending_sel);
+ /*
+ * Clear master flags /before/ clearing selector flag.
+ * atomic_readandclear_xen_ulong must contain an appropriate barrier
+ */
+ l1 = atomic_readandclear_xen_ulong(&v->evtchn_pending_sel);
l1i = pc->last_processed_l1i;
l2i = pc->last_processed_l2i;
("Received unexpected event on vCPU#%d, event bound to vCPU#%d",
PCPU_GET(cpuid), isrc->xi_cpu));
- intr_execute_handlers(&isrc->xi_intsrc, trap_frame);
+ error = intr_event_handle(isrc->xi_event, trap_frame);
+ if ( error != 0 )
+ printf("stray evchn%d: %d\n", port, error);
/*
* If this is the final port processed,
}
for (i = 0; i < nitems(s->evtchn_mask); i++)
- atomic_store_rel_long(&s->evtchn_mask[i], ~0);
+ atomic_store_rel_xen_ulong(&s->evtchn_mask[i], ~0);
/* Try to register PIRQ EOI map */
xen_intr_pirq_eoi_map = malloc(PAGE_SIZE, M_XENINTR, M_WAITOK | M_ZERO);
else
xen_intr_pirq_eoi_map_enabled = true;
- intr_register_pic(&xen_intr_pic);
- intr_register_pic(&xen_intr_pirq_pic);
-
if (bootverbose)
printf("Xen interrupt system initialized\n");
SYSINIT(xen_intr_init, SI_SUB_INTR, SI_ORDER_SECOND, xen_intr_init, NULL);
/*--------------------------- Common PIC Functions ---------------------------*/
-/**
- * Prepare this PIC for system suspension.
- */
+
+#if 0
static void
xen_intr_suspend(struct pic *unused)
{
}
}
}
+#endif
/**
* Disable a Xen interrupt source.
* \param isrc The interrupt source to disable.
*/
static void
-xen_intr_disable_intr(struct intsrc *base_isrc)
+xen_intr_disable_intr(void *arg)
{
- struct xenisrc *isrc = (struct xenisrc *)base_isrc;
+ struct xenisrc *isrc = arg;
evtchn_mask_port(isrc->xi_port);
}
+#if 0
/**
* Determine the global interrupt vector number for
* a Xen interrupt source.
return (ENODEV);
}
+#endif
+
/**
* Configure CPU affinity for interrupt source event delivery.
*
* \returns 0 if successful, otherwise an errno.
*/
static int
-xen_intr_assign_cpu(struct intsrc *base_isrc, u_int to_cpu)
+xen_intr_assign_cpu(struct xenisrc *isrc, u_int to_cpu)
{
#ifdef SMP
struct evtchn_bind_vcpu bind_vcpu;
- struct xenisrc *isrc;
u_int vcpu_id = cpu_to_vcpu_id(to_cpu);
int error;
xen_intr_intrcnt_add(to_cpu);
mtx_lock(&xen_intr_isrc_lock);
- isrc = (struct xenisrc *)base_isrc;
if (!is_valid_evtchn(isrc->xi_port)) {
mtx_unlock(&xen_intr_isrc_lock);
return (EINVAL);
#endif
}
-/* Wrapper of xen_intr_assign_cpu to use as pic callbacks */
-static int
-xen_pic_assign_cpu(struct intsrc *isrc, u_int apic_id)
-{
- return xen_intr_assign_cpu(isrc, apic_cpuid(apic_id));
-}
-
/*------------------- Virtual Interrupt Source PIC Functions -----------------*/
+#if 0
/*
* Mask a level triggered interrupt source.
*
{
}
+#endif
/*
* Enable and unmask the interrupt source.
*
* \param isrc The interrupt source to enable.
*/
static void
-xen_intr_enable_intr(struct intsrc *base_isrc)
+xen_intr_enable_intr(void *arg)
{
- struct xenisrc *isrc = (struct xenisrc *)base_isrc;
+ struct xenisrc *isrc = arg;
evtchn_unmask_port(isrc->xi_port);
}
+#if 0
/*------------------ Physical Interrupt Source PIC Functions -----------------*/
/*
* Mask a level triggered interrupt source.
return (0);
}
+#endif
/*--------------------------- Public Functions -------------------------------*/
/*------- API comments for these methods can be found in xen/xenintr.h -------*/
#ifdef SMP
if (error == 0)
- error = intr_event_bind(isrc->xi_intsrc.is_event, cpu);
+ error = intr_event_bind(isrc->xi_event, cpu);
#endif
if (error != 0) {
* masks manually so events can't fire on the wrong cpu
* during AP startup.
*/
- xen_intr_assign_cpu(&isrc->xi_intsrc, cpu);
+ xen_intr_assign_cpu(isrc, cpu);
}
#endif
dev, filter, NULL, NULL, flags,
port_handlep);
if (error == 0)
- error = intr_event_bind(isrc->xi_intsrc.is_event, cpu);
+ error = intr_event_bind(isrc->xi_event, cpu);
if (error != 0) {
evtchn_close_t close = { .port = bind_ipi.port };
* masks manually so events can't fire on the wrong cpu
* during AP startup.
*/
- xen_intr_assign_cpu(&isrc->xi_intsrc, cpu);
+ xen_intr_assign_cpu(isrc, cpu);
}
/*
return (0);
}
+#if 0
int
xen_release_msi(int vector)
{
return (0);
}
+#endif
int
xen_intr_describe(xen_intr_handle_t port_handle, const char *fmt, ...)
va_start(ap, fmt);
vsnprintf(descr, sizeof(descr), fmt, ap);
va_end(ap);
- return (intr_describe(isrc->xi_vector, isrc->xi_cookie, descr));
+
+ return (intr_event_describe_handler(isrc->xi_event, port_handle,
+ descr));
}
void
return;
if (isrc->xi_cookie != NULL)
- intr_remove_handler(isrc->xi_cookie);
+ intr_event_remove_handler(isrc->xi_cookie);
xen_intr_release_isrc(isrc);
}
if (isrc == NULL || isrc->xi_cookie != NULL)
return (EINVAL);
- error = intr_add_handler(device_get_nameunit(dev), isrc->xi_vector,
- filter, handler, arg, flags|INTR_EXCL, &isrc->xi_cookie);
+ error = intr_event_add_handler(isrc->xi_event,
+ device_get_nameunit(dev),
+ filter, handler, arg,
+ intr_priority(flags), flags|INTR_EXCL,
+ isrc->xi_cookie);
if (error != 0) {
device_printf(dev,
"xen_intr_add_handler: intr_add_handler failed: %d\n",