This allows Dom0 to manage physical hardware, redirecting the
physical interrupts to event channels.
---
sys/x86/xen/xen_intr.c | 190 +--
sys/xen/xen_intr.h | 11 +++
2 files changed, 192 insertions(+), 9 deletions(-)
diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c
index bc0781e..340e5ed 100644
--- a/sys/x86/xen/xen_intr.c
+++ b/sys/x86/xen/xen_intr.c
@@ -104,6 +104,8 @@ DPCPU_DECLARE(struct vcpu_info *, vcpu_info);
#define is_valid_evtchn(x) ((x) != 0)
+#defineEEXIST 17 /* Xen "already exists" error */
+
struct xenisrc {
struct intsrc xi_intsrc;
enum evtchn_type xi_type;
@@ -111,6 +113,9 @@ struct xenisrc {
int xi_vector; /* Global isrc vector number. */
evtchn_port_t xi_port;
int xi_pirq;
+ int xi_activehi:1;
+ int xi_edgetrigger:1;
+ int xi_configured:1;
int xi_virq;
u_int xi_close:1; /* close on unbind? */
u_int xi_needs_eoi:1;
@@ -136,6 +141,9 @@ static void xen_intr_pirq_enable_source(struct intsrc
*isrc);
static voidxen_intr_pirq_disable_source(struct intsrc *isrc, int eoi);
static voidxen_intr_pirq_eoi_source(struct intsrc *isrc);
static voidxen_intr_pirq_enable_intr(struct intsrc *isrc);
+static voidxen_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);
/**
* PIC interface for all event channel port types except physical IRQs.
@@ -163,12 +171,12 @@ struct pic xen_intr_pirq_pic = {
.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_disable_intr,
+ .pic_disable_intr = xen_intr_pirq_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_config_intr= xen_intr_pirq_config_intr,
.pic_assign_cpu = xen_intr_assign_cpu
};
@@ -282,11 +290,10 @@ xen_intr_find_unused_isrc(enum evtchn_type type)
* object or NULL.
*/
static struct xenisrc *
-xen_intr_alloc_isrc(enum evtchn_type type)
+xen_intr_alloc_isrc(enum evtchn_type type, int vector)
{
static int warned;
struct xenisrc *isrc;
- int vector;
KASSERT(mtx_owned(&xen_intr_isrc_lock), ("Evtchn alloc lock not held"));
@@ -297,12 +304,19 @@ xen_intr_alloc_isrc(enum evtchn_type type)
}
return (NULL);
}
- vector = FIRST_EVTCHN_INT + xen_intr_isrc_count;
- xen_intr_isrc_count++;
+
+ if (type != EVTCHN_TYPE_PIRQ) {
+ vector = FIRST_EVTCHN_INT + xen_intr_isrc_count;
+ xen_intr_isrc_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 = &xen_intr_pic;
+ 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);
@@ -388,7 +402,7 @@ xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t
local_port,
mtx_lock(&xen_intr_isrc_lock);
isrc = xen_intr_find_unused_isrc(type);
if (isrc == NULL) {
- isrc = xen_intr_alloc_isrc(type);
+ isrc = xen_intr_alloc_isrc(type, 0);
if (isrc == NULL) {
mtx_unlock(&xen_intr_isrc_lock);
return (ENOSPC);
@@ -592,6 +606,10 @@ xen_intr_init(void *dummy __unused)
}
intr_register_pic(&xen_intr_pic);
+ intr_register_pic(&xen_intr_pirq_pic);
+
+ if (bootverbose)
+ printf("Xen interrupt system initialized\n");
return (0);
}
@@ -925,6 +943,9 @@ xen_intr_pirq_disable_source(struct intsrc *base_isrc, int
eoi)
isrc = (struct xenisrc *)base_isrc;
evtchn_mask_port(isrc->xi_port);
+
+ if (eoi == PIC_EOI)
+ xen_intr_pirq_eoi_source(base_isrc);
}
/*
@@ -966,8 +987,115 @@ xen_intr_pirq_eoi_source(struct intsrc *base_isrc)
* \param isrc The interrupt source to enable.
*/
static void
-xen_intr_pirq_enable_intr(struct intsrc *isrc)
+xen_intr_pirq_enable_intr(struct intsrc *base_isrc)
+{
+ struct xenisrc *isrc;
+ struct evtchn_bind_pirq bind_pirq;
+ struct physdev_irq_stat