Port-xen archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: interrupt cleanup #2
Cherry G.Mathew <cherry%zyx.in@localhost> writes:
[...]
>
> The next one will be a bit intrusive.
Points to note:
+int xen_pirq_get_vector_from_token(struct xen_pic *, int);
+int xen_pirq_get_token_from_vector(struct xen_pic *, int);
+void xen_pirq_save_port_token(struct xen_pic *, int, int);
+int xen_pirq_get_port_from_token(struct xen_pic *, int);
+int xen_pirq_get_token_from_pirq(intr_handle_t);
These are currently only declared, not defined. It's a preview into the
next patch, but an example usecase can be found in xen/x86/xen_pic.c
introduced in this patch.
The idea is to introduce the xen_pic structure, and use it minimally
with no functional changes.
--
~cherry
# HG changeset patch
# User Cherry G. Mathew <cherry%NetBSD.org@localhost>
# Date 1535448340 0
# Tue Aug 28 09:25:40 2018 +0000
# Branch cherry-xen
# Node ID 08eaeb8726ab4befca6b61d17de6594e1e4cc8de
# Parent 68df2d41794468efd9f8572591d3e05ba4a99c47
[mq]: 0003-Start-using-xen_pic.c-but-not-all-of-it
diff -r 68df2d417944 -r 08eaeb8726ab sys/arch/x86/include/pic.h
--- a/sys/arch/x86/include/pic.h Tue Aug 28 05:10:20 2018 +0000
+++ b/sys/arch/x86/include/pic.h Tue Aug 28 09:25:40 2018 +0000
@@ -23,6 +23,9 @@
struct intrstub *pic_edge_stubs;
struct ioapic_softc *pic_ioapic; /* if pic_type == PIC_IOAPIC */
struct msipic *pic_msipic; /* if (pic_type == PIC_MSI) || (pic_type == PIC_MSIX) */
+#if defined(XEN)
+ struct xen_pic *pic_xen;
+#endif
};
/*
diff -r 68df2d417944 -r 08eaeb8726ab sys/arch/x86/x86/ioapic.c
--- a/sys/arch/x86/x86/ioapic.c Tue Aug 28 05:10:20 2018 +0000
+++ b/sys/arch/x86/x86/ioapic.c Tue Aug 28 09:25:40 2018 +0000
@@ -552,6 +552,8 @@
ioapic_unlock(sc, flags);
}
+extern struct xen_pic pic_xen; /* XXX: */
+
static void
ioapic_addroute(struct pic *pic, struct cpu_info *ci, int pin,
int idtvec, int type)
@@ -574,14 +576,14 @@
*/
int port, irq;
- irq = vect2irq[idtvec];
+ irq = pic_xen.vect2irq[idtvec];
KASSERT(irq != 0);
port = bind_pirq_to_evtch(irq);
KASSERT(port < NR_EVENT_CHANNELS);
KASSERT(port >= 0);
- KASSERT(irq2port[irq] == 0);
- irq2port[irq] = port + 1;
+ KASSERT(pic_xen.irq2port[irq] == 0);
+ pic_xen.irq2port[irq] = port + 1;
xen_atomic_set_bit(&ci->ci_evtmask[0], port);
#endif
@@ -597,7 +599,7 @@
#if defined(XEN)
int port, irq;
- irq = vect2irq[idtvec];
+ irq = pic_xen.vect2irq[idtvec];
port = unbind_pirq_from_evtch(irq);
KASSERT(port < NR_EVENT_CHANNELS);
diff -r 68df2d417944 -r 08eaeb8726ab sys/arch/xen/conf/files.xen
--- a/sys/arch/xen/conf/files.xen Tue Aug 28 05:10:20 2018 +0000
+++ b/sys/arch/xen/conf/files.xen Tue Aug 28 09:25:40 2018 +0000
@@ -102,6 +102,7 @@
file arch/xen/xen/clock.c
file arch/x86/isa/rtc.c dom0ops
file arch/xen/xen/evtchn.c
+file arch/xen/x86/xen_pic.c
file arch/xen/xen/xengnt.c
diff -r 68df2d417944 -r 08eaeb8726ab sys/arch/xen/include/evtchn.h
--- a/sys/arch/xen/include/evtchn.h Tue Aug 28 05:10:20 2018 +0000
+++ b/sys/arch/xen/include/evtchn.h Tue Aug 28 09:25:40 2018 +0000
@@ -65,6 +65,8 @@
int pic_type;
int pirq;
int evtch;
+ struct pic *pic;
+ struct cpu_info *ci;
int (*func)(void *);
void *arg;
};
diff -r 68df2d417944 -r 08eaeb8726ab sys/arch/xen/include/intr.h
--- a/sys/arch/xen/include/intr.h Tue Aug 28 05:10:20 2018 +0000
+++ b/sys/arch/xen/include/intr.h Tue Aug 28 09:25:40 2018 +0000
@@ -62,15 +62,29 @@
};
extern struct intrstub xenev_stubs[];
-extern int irq2vect[256];
-extern int vect2irq[256];
-extern int irq2port[NR_EVENT_CHANNELS]; /* actually port + 1, so that 0 is invaid */
+
+/* pirq binding related mappings */
+struct xen_pic {
+ int irq2vect[256];
+ int vect2irq[256];
+ /*
+ * Note: The 'irq' here comes from MP/apic tables, not xen.
+ * Later we want this to be a lookup for MSI etc.
+ * See: intr.c: intr_establish_xname() for usage eg:
+ */
+ int irq2port[256]; /* actually port + 1, so that 0 is invaid */
+};
#ifdef MULTIPROCESSOR
int xen_intr_biglock_wrapper(void *);
#endif
#if defined(DOM0OPS) || NPCI > 0
+int xen_pirq_get_vector_from_token(struct xen_pic *, int);
+int xen_pirq_get_token_from_vector(struct xen_pic *, int);
+void xen_pirq_save_port_token(struct xen_pic *, int, int);
+int xen_pirq_get_port_from_token(struct xen_pic *, int);
+int xen_pirq_get_token_from_pirq(intr_handle_t);
int xen_pirq_alloc(intr_handle_t *, int);
#endif /* defined(DOM0OPS) || NPCI > 0 */
diff -r 68df2d417944 -r 08eaeb8726ab sys/arch/xen/x86/pintr.c
--- a/sys/arch/xen/x86/pintr.c Tue Aug 28 05:10:20 2018 +0000
+++ b/sys/arch/xen/x86/pintr.c Tue Aug 28 09:25:40 2018 +0000
@@ -142,9 +142,6 @@
struct intrstub x2apic_edge_stubs[MAX_INTR_SOURCES] = {{0,0}};
struct intrstub x2apic_level_stubs[MAX_INTR_SOURCES] = {{0,0}};
#include <machine/i82093var.h>
-int irq2port[NR_EVENT_CHANNELS] = {0}; /* actually port + 1, so that 0 is invaid */
-int irq2vect[256] = {0};
-int vect2irq[256] = {0};
#endif /* NIOAPIC */
#if NACPICA > 0
#include <machine/mpconfig.h>
@@ -159,6 +156,7 @@
#endif
#if defined(DOM0OPS) || NPCI > 0
+extern struct xen_pic pic_xen; /* XXX: */
int
xen_pirq_alloc(intr_handle_t *pirq, int type)
{
@@ -183,7 +181,7 @@
int pin = APIC_IRQ_PIN(*pirq);
if (*pirq & APIC_INT_VIA_APIC) {
- irq = vect2irq[ioapic->sc_pins[pin].ip_vector];
+ irq = pic_xen.vect2irq[ioapic->sc_pins[pin].ip_vector];
if (ioapic->sc_pins[pin].ip_vector == 0 || irq == 0) {
/* allocate IRQ */
irq = APIC_IRQ_LEGACY_IRQ(*pirq);
@@ -199,10 +197,10 @@
panic("PHYSDEVOP_ASSIGN_VECTOR irq %d", irq);
goto retry;
}
- KASSERT(irq2vect[irq] == 0);
- irq2vect[irq] = op.u.irq_op.vector;
- KASSERT(vect2irq[op.u.irq_op.vector] == 0);
- vect2irq[op.u.irq_op.vector] = irq;
+ KASSERT(pic_xen.irq2vect[irq] == 0);
+ pic_xen.irq2vect[irq] = op.u.irq_op.vector;
+ KASSERT(pic_xen.vect2irq[op.u.irq_op.vector] == 0);
+ pic_xen.vect2irq[op.u.irq_op.vector] = irq;
pic->pic_addroute(pic, &phycpu_info_primary, pin,
op.u.irq_op.vector, type);
}
@@ -211,21 +209,21 @@
} else
#endif /* NIOAPIC */
{
- if (irq2port[irq] == 0) {
+ if (pic_xen.irq2port[irq] == 0) {
op.cmd = PHYSDEVOP_ASSIGN_VECTOR;
op.u.irq_op.irq = irq;
if (HYPERVISOR_physdev_op(&op) < 0) {
panic("PHYSDEVOP_ASSIGN_VECTOR irq %d", irq);
}
- KASSERT(irq2vect[irq] == 0);
- irq2vect[irq] = op.u.irq_op.vector;
- KASSERT(vect2irq[op.u.irq_op.vector] == 0);
- vect2irq[op.u.irq_op.vector] = irq;
- KASSERT(irq2port[irq] == 0);
- irq2port[irq] = bind_pirq_to_evtch(irq) + 1;
+ KASSERT(pic_xen.irq2vect[irq] == 0);
+ pic_xen.irq2vect[irq] = op.u.irq_op.vector;
+ KASSERT(pic_xen.vect2irq[op.u.irq_op.vector] == 0);
+ pic_xen.vect2irq[op.u.irq_op.vector] = irq;
+ KASSERT(pic_xen.irq2port[irq] == 0);
+ pic_xen.irq2port[irq] = bind_pirq_to_evtch(irq) + 1;
}
}
- KASSERT(irq2port[irq] > 0);
- return (irq2port[irq] - 1);
+ KASSERT(pic_xen.irq2port[irq] > 0);
+ return (pic_xen.irq2port[irq] - 1);
}
#endif /* defined(DOM0OPS) || NPCI > 0 */
diff -r 68df2d417944 -r 08eaeb8726ab sys/arch/xen/x86/xen_pic.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/xen/x86/xen_pic.c Tue Aug 28 09:25:40 2018 +0000
@@ -0,0 +1,343 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software written under contract with The NetBSD Foundation
+ * by Cherry G. Mathew <cherry%NetBSD.org@localhost>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include "opt_xen.h"
+
+#include <sys/param.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <machine/i82093var.h>
+
+#include "ioapic.h"
+
+#include <xen/evtchn.h>
+
+extern struct cpu_info phycpu_info_primary;
+
+static void xen_pic_mask(struct pic *, int);
+static void xen_pic_unmask(struct pic *, int);
+static void xen_pic_addroute(struct pic *, struct cpu_info *, int, int, int);
+static void xen_pic_delroute(struct pic *, struct cpu_info *, int, int, int);
+static bool xen_pic_trymask(struct pic *, int);
+
+/* XXX: static */ struct xen_pic pic_xen = {
+ .irq2port = {0},
+ .irq2vect = {0},
+ .vect2irq = {0}
+};
+
+struct pic xen_pic = {
+ .pic_name = "xenev0",
+ .pic_type = PIC_XEN,
+ .pic_vecbase = 0,
+ .pic_apicid = 0,
+ .pic_lock = __SIMPLELOCK_UNLOCKED,
+ .pic_hwmask = xen_pic_mask,
+ .pic_hwunmask = xen_pic_unmask,
+ .pic_addroute = xen_pic_addroute,
+ .pic_delroute = xen_pic_delroute,
+ .pic_trymask = xen_pic_trymask,
+ .pic_level_stubs = xenev_stubs,
+ .pic_edge_stubs = xenev_stubs,
+ .pic_xen = &pic_xen,
+};
+
+/*
+ * We try to stick to the traditional x86 PIC semantics wrt Xen
+ * events.
+ *
+ * PIC pins exist in a global namespace which may be hierarchical, and
+ * are mapped to a cpu bus concept called 'IRQ' numbers, which are
+ * also global, but linear. Thus a PIC, pin tuple will always map to
+ * an IRQ number. These tuples can alias to the same IRQ number, thus
+ * causing IRQ "sharing". IRQ numbers can be bound to specific CPUs,
+ * and to specific callback vector indices on the CPU called idt_vec,
+ * which are aliases to handlers meant to run on destination
+ * CPUs. This binding can also happen at interrupt time and resolved
+ * 'round-robin' between all CPUs, depending on the lapic setup. In
+ * this case, all CPUs need to have identical idt_vec->handler
+ * mappings.
+ *
+ * The job of pic_addroute() is to setup the 'wiring' between the
+ * source pin, and the destination CPU callback offset, ideally on a
+ * specific CPU in MP systems (or 'round-robin').
+ *
+ * On Xen, a global namespace of 'events' exist, which are initially
+ * bound to nothing. This is similar to the relationship between
+ * realworld IRQ numbers wrt PIC pins, since before routing, IRQ
+ * numbers by themselves have no causal connection setup with the real
+ * world. (Except for the hardwired cases on the PC Architecture,
+ * which we ignore for the purpose of this description). However the
+ * really important routing is from pin to idt_vec. On PIC_XEN, all
+ * three (pin, irq, idt_vec) belong to the same namespace and are
+ * identical. Further, the mapping between idt_vec and the actual
+ * callback handler is setup via calls to the evtchn.h api - this
+ * last bit is analogous to x86/idt.c:idt_vec_set() on real h/w
+ *
+ * For now we handle two cases:
+ * - IPC style events - eg: timer, PV devices, etc.
+ * - dom0 physical irq bound events.
+ *
+ * In the case of IPC style events, we currently externalise the
+ * event binding by using evtchn.h functions. From the POV of
+ * PIC_XEN , 'pin' , 'irq' and 'idt_vec' are all identical to the
+ * port number of the event.
+ *
+ * In the case of dom0 physical irq bound events, we currently effect
+ * event binding by exporting evtchn.h functions. From the POV of
+ * PIC_LAPIC/PIC_IOAPIC, the 'pin' is the hardware pin, the 'irq' is
+ * the x86 global irq number - the port number is extracted out of a
+ * global array (this is currently kludgy and breaks API abstraction)
+ * and the binding happens during pic_addroute() of the ioapic.
+ *
+ * Later when we integrate more tightly with x86/intr.c, we will be
+ * able to conform better to the (PIC_LAPIC/PIC_IOAPIC)->PIC_XEN
+ * cascading model.
+ */
+
+/* PIC callbacks */
+/* pic "pin"s are conceptually mapped to event port numbers */
+static void
+xen_pic_mask(struct pic *pic, int pin)
+{
+ evtchn_port_t evtchn = pin;
+
+ KASSERT(pic->pic_type == PIC_XEN);
+ KASSERT(evtchn < NR_EVENT_CHANNELS);
+
+ hypervisor_mask_event(evtchn);
+}
+
+static void
+xen_pic_unmask(struct pic *pic, int pin)
+{
+ evtchn_port_t evtchn = pin;
+
+ KASSERT(pic->pic_type == PIC_XEN);
+ KASSERT(evtchn < NR_EVENT_CHANNELS);
+
+ hypervisor_unmask_event(evtchn);
+}
+
+intr_handle_t
+xen_pirq_assign(intr_handle_t );
+
+static void
+xen_pic_addroute(struct pic *pic, struct cpu_info *ci, int src, int dest, int type)
+{
+
+#if notyet
+ /* Events are simulated as level triggered interrupts */
+ evtchn_op_t op;
+#endif
+
+ KASSERT(ci != NULL);
+
+ switch (pic->pic_type) {
+ case PIC_XEN:
+ /* Pass through! */
+ break;
+#if notyet
+#if defined(DOM0OPS) || NPCI > 0
+ int xen_vector, token; /* CPU vector, irq returned by xen */
+ case PIC_I8259:
+ case PIC_LAPIC:
+ case PIC_IOAPIC:
+
+ /*
+ * Route a hardware PIC pin binding through
+ * a specified port.
+ */
+
+ /*
+ * Tell xen about our intentions.
+ *
+ * But first get a vector binding. What's returned to
+ * us is a handle to that vector. Xen calls it a
+ * "pseudo IRQ" (pirq).
+ *
+ * Note that in the case of ioapics, we expect the src
+ * to contain bitfielded info in src.
+ */
+
+ token = xen_pirq_alloc(src);
+
+ xen_vector = xen_pirq_get_vector_from_token(xen_pic.pic_xen, token);
+
+#if NIOAPIC > 0
+ /*
+ * Add the ioapic route - we can only route it via
+ * the BSP for now.
+ */
+
+ pic->pic_addroute(pic, &phycpu_info_primary, APIC_IRQ_PIN(src),
+ xen_vector, type);
+
+
+#endif /* NIOAPIC > 0 */
+
+ /*
+ * Now we can bind+alloc (no API to do this in a
+ * degenerate fashion) this handle to a port.
+ */
+
+ if (token >= NR_PIRQS) {
+ panic("pirq %d out of bound, increase NR_PIRQS", token);
+ }
+
+ op.cmd = EVTCHNOP_bind_pirq;
+ op.u.bind_pirq.pirq = token;
+ op.u.bind_pirq.flags = BIND_PIRQ__WILL_SHARE;
+ if (HYPERVISOR_event_channel_op(&op) != 0)
+ panic("Failed to bind physical IRQ %d\n", token);
+ dest = op.u.bind_pirq.port;
+
+ KASSERT(dest < NR_EVENT_CHANNELS);
+ KASSERT(dest >= 0);
+ xen_pirq_save_port_token(xen_pic.pic_xen, dest, token);
+ break;
+
+ case PIC_MSI:
+ case PIC_MSIX:
+#endif /* defined(DOM0OPS) || NPCI > 0 */
+#endif /* notyet */
+ default:
+ panic("/* TODO */");
+ break;
+
+ }
+
+#if notyet
+ /* Bind dest port to the routed vcpu */
+ op.cmd = EVTCHNOP_bind_vcpu;
+ op.u.bind_vcpu.vcpu = ci->ci_cpuid;
+ op.u.bind_vcpu.port = dest;
+
+#define PRIuCPUID "lu" /* XXX: move this somewhere more appropriate */
+
+ if (HYPERVISOR_event_channel_op(&op) != 0)
+ panic("Failed to bind port %d to VCPU %"PRIuCPUID"\n", dest, ci->ci_cpuid);
+#endif /* Not yet */
+ /* Give the event handler a hint about our vcpu preference */
+ xen_atomic_set_bit(&ci->ci_evtmask[0], dest);
+
+}
+
+static void
+xen_pic_delroute(struct pic *pic, struct cpu_info *ci, int src, int dest, int type)
+{
+ KASSERT(ci != NULL);
+
+ switch (pic->pic_type) {
+ case PIC_XEN:
+ /* Pass through! */
+ break;
+
+#if notyet
+#if defined(DOM0OPS) || NPCI > 0 && notyet
+ case PIC_I8259:
+ case PIC_LAPIC:
+ /* NOP */
+ break;
+
+ case PIC_IOAPIC:
+ pic->pic_delroute(pic, &phycpu_info_primary, src,
+ pic->pic_ioapic->sc_pins[src].ip_vector, type);
+ case PIC_MSI:
+ case PIC_MSIX:
+#endif
+#endif
+ default:
+ panic("/* TODO */");
+ break;
+
+ }
+
+ /*
+ * Unbind the destination port. Thus the source won't "route"
+ * to the destination.
+ *
+ * If the source was a hardware PIC pin binding:
+ *
+ * There currently isn't a documented way to remove this
+ * binding, so we just go ahead and close the destination port
+ * in the hope that it will be unbound in the process.
+ */
+
+ evtchn_op_t op;
+ op.cmd = EVTCHNOP_close;
+ op.u.close.port = dest;
+ if (HYPERVISOR_event_channel_op(&op) != 0)
+ panic("Failed to unbind physical IRQ %d\n", src);
+
+ xen_atomic_clear_bit(&ci->ci_evtmask[0], dest);
+}
+
+/*
+ * xen_pic_trymask(pic, pin)
+ *
+ * If there are interrupts pending on the bus-shared pic, return
+ * false. Otherwise, mask interrupts on the bus-shared pic and
+ * return true.
+ */
+static bool
+xen_pic_trymask(struct pic *pic, int pin)
+{
+ volatile struct shared_info *s = HYPERVISOR_shared_info;
+ unsigned long masked __diagused;
+
+ /* Mask it. */
+ masked = xen_atomic_test_and_set_bit(&s->evtchn_mask[0], pin);
+
+ /*
+ * Caller is responsible for calling trymask only when the
+ * interrupt pin is not masked, and for serializing calls to
+ * trymask.
+ */
+ KASSERT(!masked);
+
+ /*
+ * Check whether there were any interrupts pending when we
+ * masked it. If there were, unmask and abort.
+ */
+ if (xen_atomic_test_bit(&s->evtchn_pending[0], pin)) {
+ xen_atomic_clear_bit(&s->evtchn_mask[0], pin);
+ return false;
+ }
+
+ /* Success: masked, not pending. */
+ return true;
+}
+
diff -r 68df2d417944 -r 08eaeb8726ab sys/arch/xen/xen/evtchn.c
--- a/sys/arch/xen/xen/evtchn.c Tue Aug 28 05:10:20 2018 +0000
+++ b/sys/arch/xen/xen/evtchn.c Tue Aug 28 09:25:40 2018 +0000
@@ -116,81 +116,6 @@
};
#endif
-static void xen_evtchn_mask(struct pic *, int);
-static void xen_evtchn_unmask(struct pic *, int);
-static void xen_evtchn_addroute(struct pic *, struct cpu_info *, int, int, int);
-static void xen_evtchn_delroute(struct pic *, struct cpu_info *, int, int, int);
-static bool xen_evtchn_trymask(struct pic *, int);
-
-
-struct pic xen_pic = {
- .pic_name = "xenev0",
- .pic_type = PIC_XEN,
- .pic_vecbase = 0,
- .pic_apicid = 0,
- .pic_lock = __SIMPLELOCK_UNLOCKED,
- .pic_hwmask = xen_evtchn_mask,
- .pic_hwunmask = xen_evtchn_unmask,
- .pic_addroute = xen_evtchn_addroute,
- .pic_delroute = xen_evtchn_delroute,
- .pic_trymask = xen_evtchn_trymask,
- .pic_level_stubs = xenev_stubs,
- .pic_edge_stubs = xenev_stubs,
-};
-
-/*
- * We try to stick to the traditional x86 PIC semantics wrt Xen
- * events.
- *
- * PIC pins exist in a global namespace which may be hierarchical, and
- * are mapped to a cpu bus concept called 'IRQ' numbers, which are
- * also global, but linear. Thus a PIC, pin tuple will always map to
- * an IRQ number. These tuples can alias to the same IRQ number, thus
- * causing IRQ "sharing". IRQ numbers can be bound to specific CPUs,
- * and to specific callback vector indices on the CPU called idt_vec,
- * which are aliases to handlers meant to run on destination
- * CPUs. This binding can also happen at interrupt time and resolved
- * 'round-robin' between all CPUs, depending on the lapic setup. In
- * this case, all CPUs need to have identical idt_vec->handler
- * mappings.
- *
- * The job of pic_addroute() is to setup the 'wiring' between the
- * source pin, and the destination CPU handler, ideally on a specific
- * CPU in MP systems (or 'round-robin').
- *
- * On Xen, a global namespace of 'events' exist, which are initially
- * bound to nothing. This is similar to the relationship between
- * realworld realworld IRQ numbers wrt PIC pins, since before routing,
- * IRQ numbers by themselves have no causal connection setup with the
- * real world. (Except for the hardwired cases on the PC Architecture,
- * which we ignore for the purpose of this description). However the
- * really important routing is from pin to idt_vec. On PIC_XEN, all
- * three (pic, irq, idt_vec) belong to the same namespace and are
- * identical. Further, the mapping between idt_vec and the actual
- * callback handler is setup via calls to the evtchn.h api - this
- * last bit is analogous to x86/idt.c:idt_vec_set() on real h/w
- *
- * For now we handle two cases:
- * - IPC style events - eg: timer, PV devices, etc.
- * - dom0 physical irq bound events.
- *
- * In the case of IPC style events, we currently externalise the
- * event binding by using evtchn.h functions. From the POV of
- * PIC_XEN , 'pin' , 'irq' and 'idt_vec' are all identical to the
- * port number of the event.
- *
- * In the case of dom0 physical irq bound events, we currently
- * event binding by exporting evtchn.h functions. From the POV of
- * PIC_LAPIC/PIC_IOAPIC, the 'pin' is the hardware pin, the 'irq' is
- * the x86 global irq number - the port number is extracted out of a
- * global array (this is currently kludgy and breaks API abstraction)
- * and the binding happens during pic_addroute() of the ioapic.
- *
- * Later when we integrate more tightly with x86/intr.c, we will be
- * able to conform better to (PIC_LAPIC/PIC_IOAPIC)->PIC_XEN
- * cascading model.
- */
-
int debug_port = -1;
// #define IRQ_DEBUG 4
@@ -428,113 +353,6 @@
#define PRIuCPUID "lu" /* XXX: move this somewhere more appropriate */
-/* PIC callbacks */
-/* pic "pin"s are conceptually mapped to event port numbers */
-static void
-xen_evtchn_mask(struct pic *pic, int pin)
-{
- evtchn_port_t evtchn = pin;
-
- KASSERT(pic->pic_type == PIC_XEN);
- KASSERT(evtchn < NR_EVENT_CHANNELS);
-
- hypervisor_mask_event(evtchn);
-
-}
-
-static void
-xen_evtchn_unmask(struct pic *pic, int pin)
-{
- evtchn_port_t evtchn = pin;
-
- KASSERT(pic->pic_type == PIC_XEN);
- KASSERT(evtchn < NR_EVENT_CHANNELS);
-
- hypervisor_unmask_event(evtchn);
-
-}
-
-
-static void
-xen_evtchn_addroute(struct pic *pic, struct cpu_info *ci, int pin, int idt_vec, int type)
-{
-
- evtchn_port_t evtchn = pin;
-
- /* Events are simulated as level triggered interrupts */
- KASSERT(type == IST_LEVEL);
-
- KASSERT(evtchn < NR_EVENT_CHANNELS);
-#if notyet
- evtchn_port_t boundport = idt_vec;
-#endif
-
- KASSERT(pic->pic_type == PIC_XEN);
-
- xen_atomic_set_bit(&ci->ci_evtmask[0], evtchn);
-
-}
-
-static void
-xen_evtchn_delroute(struct pic *pic, struct cpu_info *ci, int pin, int idt_vec, int type)
-{
- /*
- * XXX: In the future, this is a great place to
- * 'unbind' events to underlying events and cpus.
- * For now, just disable interrupt servicing on this cpu for
- * this pin aka cpu.
- */
- evtchn_port_t evtchn = pin;
-
- /* Events are simulated as level triggered interrupts */
- KASSERT(type == IST_LEVEL);
-
- KASSERT(evtchn < NR_EVENT_CHANNELS);
-#if notyet
- evtchn_port_t boundport = idt_vec;
-#endif
-
- KASSERT(pic->pic_type == PIC_XEN);
-
- xen_atomic_clear_bit(&ci->ci_evtmask[0], evtchn);
-}
-
-/*
- * xen_evtchn_trymask(pic, pin)
- *
- * If there are interrupts pending on the bus-shared pic, return
- * false. Otherwise, mask interrupts on the bus-shared pic and
- * return true.
- */
-static bool
-xen_evtchn_trymask(struct pic *pic, int pin)
-{
- volatile struct shared_info *s = HYPERVISOR_shared_info;
- unsigned long masked __diagused;
-
- /* Mask it. */
- masked = xen_atomic_test_and_set_bit(&s->evtchn_mask[0], pin);
-
- /*
- * Caller is responsible for calling trymask only when the
- * interrupt pin is not masked, and for serializing calls to
- * trymask.
- */
- KASSERT(!masked);
-
- /*
- * Check whether there were any interrupts pending when we
- * masked it. If there were, unmask and abort.
- */
- if (xen_atomic_test_bit(&s->evtchn_pending[0], pin)) {
- xen_atomic_clear_bit(&s->evtchn_mask[0], pin);
- return false;
- }
-
- /* Success: masked, not pending. */
- return true;
-}
-
evtchn_port_t
bind_vcpu_to_evtch(cpuid_t vcpu)
{
Home |
Main Index |
Thread Index |
Old Index