[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH 09/16] xen/evtchn: support evtchn in xenhost_t
Largely mechanical patch that adds a new param, xenhost_t * to the evtchn interfaces. The evtchn port instead of being domain unique, is now scoped to xenhost_t. As part of upcall handling we now look at all the xenhosts and, for evtchn_2l, the xenhost's shared_info and vcpu_info. Other than this event handling is largley unchanged. Note that the IPI, timer, VIRQ, FUNCTION, PMU etc vectors remain attached to xh_default. Only interdomain evtchns are allowable as xh_remote. TODO: - to minimize the changes, evtchn FIFO is disabled for now. Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx> --- arch/x86/pci/xen.c | 16 +- arch/x86/xen/enlighten_hvm.c | 2 +- arch/x86/xen/irq.c | 2 +- arch/x86/xen/smp.c | 16 +- arch/x86/xen/smp_pv.c | 4 +- arch/x86/xen/time.c | 5 +- arch/x86/xen/xen-ops.h | 1 + arch/x86/xen/xenhost.c | 16 + drivers/block/xen-blkback/xenbus.c | 2 +- drivers/block/xen-blkfront.c | 2 +- drivers/input/misc/xen-kbdfront.c | 2 +- drivers/net/xen-netback/interface.c | 8 +- drivers/net/xen-netfront.c | 6 +- drivers/pci/xen-pcifront.c | 2 +- drivers/xen/acpi.c | 2 + drivers/xen/balloon.c | 2 +- drivers/xen/events/Makefile | 1 - drivers/xen/events/events_2l.c | 188 +++++----- drivers/xen/events/events_base.c | 379 ++++++++++++--------- drivers/xen/events/events_fifo.c | 2 +- drivers/xen/events/events_internal.h | 78 ++--- drivers/xen/evtchn.c | 22 +- drivers/xen/fallback.c | 1 + drivers/xen/gntalloc.c | 8 +- drivers/xen/gntdev.c | 8 +- drivers/xen/mcelog.c | 2 +- drivers/xen/pcpu.c | 2 +- drivers/xen/preempt.c | 1 + drivers/xen/privcmd.c | 1 + drivers/xen/sys-hypervisor.c | 2 +- drivers/xen/time.c | 2 +- drivers/xen/xen-pciback/xenbus.c | 2 +- drivers/xen/xen-scsiback.c | 5 +- drivers/xen/xenbus/xenbus_client.c | 2 +- drivers/xen/xenbus/xenbus_comms.c | 6 +- drivers/xen/xenbus/xenbus_probe.c | 1 + drivers/xen/xenbus/xenbus_probe_backend.c | 1 + drivers/xen/xenbus/xenbus_probe_frontend.c | 1 + drivers/xen/xenbus/xenbus_xs.c | 1 + include/xen/events.h | 45 +-- include/xen/xenhost.h | 17 + 41 files changed, 483 insertions(+), 383 deletions(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index d1a3b9f08289..9aa591b5fa3b 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -19,6 +19,8 @@ #include <asm/pci_x86.h> #include <asm/xen/hypervisor.h> +#include <xen/interface/xen.h> +#include <xen/xenhost.h> #include <xen/features.h> #include <xen/events.h> @@ -46,7 +48,7 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev) if (gsi < nr_legacy_irqs()) share = 0; - rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront"); + rc = xen_bind_pirq_gsi_to_irq(xh_default, gsi, pirq, share, "pcifront"); if (rc < 0) { dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n", gsi, pirq, rc); @@ -96,7 +98,7 @@ static int xen_register_pirq(u32 gsi, int gsi_override, int triggering, if (gsi_override >= 0) gsi = gsi_override; - irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name); + irq = xen_bind_pirq_gsi_to_irq(xh_default, gsi, map_irq.pirq, shareable, name); if (irq < 0) goto out; @@ -180,7 +182,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) goto error; i = 0; for_each_pci_msi_entry(msidesc, dev) { - irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], + irq = xen_bind_pirq_msi_to_irq(xh_default, dev, msidesc, v[i], (type == PCI_CAP_ID_MSI) ? nvec : 1, (type == PCI_CAP_ID_MSIX) ? "pcifront-msi-x" : @@ -234,7 +236,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return 1; for_each_pci_msi_entry(msidesc, dev) { - pirq = xen_allocate_pirq_msi(dev, msidesc); + pirq = xen_allocate_pirq_msi(xh_default, dev, msidesc); if (pirq < 0) { irq = -ENODEV; goto error; @@ -242,7 +244,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) xen_msi_compose_msg(dev, pirq, &msg); __pci_write_msi_msg(msidesc, &msg); dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); - irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, + irq = xen_bind_pirq_msi_to_irq(xh_default, dev, msidesc, pirq, (type == PCI_CAP_ID_MSI) ? nvec : 1, (type == PCI_CAP_ID_MSIX) ? "msi-x" : "msi", @@ -337,7 +339,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) goto out; } - ret = xen_bind_pirq_msi_to_irq(dev, msidesc, map_irq.pirq, + ret = xen_bind_pirq_msi_to_irq(xh_default, dev, msidesc, map_irq.pirq, (type == PCI_CAP_ID_MSI) ? nvec : 1, (type == PCI_CAP_ID_MSIX) ? "msi-x" : "msi", domid); @@ -496,7 +498,7 @@ int __init pci_xen_initial_domain(void) } if (0 == nr_ioapics) { for (irq = 0; irq < nr_legacy_irqs(); irq++) - xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic"); + xen_bind_pirq_gsi_to_irq(xh_default, irq, irq, 0, "xt-pic"); } return 0; } diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c index c1981a3e4989..efe483ceeb9a 100644 --- a/arch/x86/xen/enlighten_hvm.c +++ b/arch/x86/xen/enlighten_hvm.c @@ -266,7 +266,7 @@ static void __init xen_hvm_guest_init(void) xen_hvm_smp_init(); WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_hvm, xen_cpu_dead_hvm)); xen_unplug_emulated_devices(); - x86_init.irqs.intr_init = xen_init_IRQ; + x86_init.irqs.intr_init = xenhost_init_IRQ; xen_hvm_init_time_ops(); xen_hvm_init_mmu_ops(); diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index f760a6abfb1e..3267c3505a64 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c @@ -170,5 +170,5 @@ static const struct pv_irq_ops xen_irq_ops __initconst = { void __init xen_init_irq_ops(void) { pv_ops.irq = xen_irq_ops; - x86_init.irqs.intr_init = xen_init_IRQ; + x86_init.irqs.intr_init = xenhost_init_IRQ; } diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 867524be0065..c186d868dc5c 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -66,7 +66,7 @@ int xen_smp_intr_init(unsigned int cpu) char *resched_name, *callfunc_name, *debug_name; resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu); - rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, + rc = bind_ipi_to_irqhandler(xh_default, XEN_RESCHEDULE_VECTOR, cpu, xen_reschedule_interrupt, IRQF_PERCPU|IRQF_NOBALANCING, @@ -78,7 +78,7 @@ int xen_smp_intr_init(unsigned int cpu) per_cpu(xen_resched_irq, cpu).name = resched_name; callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu); - rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, + rc = bind_ipi_to_irqhandler(xh_default, XEN_CALL_FUNCTION_VECTOR, cpu, xen_call_function_interrupt, IRQF_PERCPU|IRQF_NOBALANCING, @@ -90,7 +90,7 @@ int xen_smp_intr_init(unsigned int cpu) per_cpu(xen_callfunc_irq, cpu).name = callfunc_name; debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu); - rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt, + rc = bind_virq_to_irqhandler(xh_default, VIRQ_DEBUG, cpu, xen_debug_interrupt, IRQF_PERCPU | IRQF_NOBALANCING, debug_name, NULL); if (rc < 0) @@ -99,7 +99,7 @@ int xen_smp_intr_init(unsigned int cpu) per_cpu(xen_debug_irq, cpu).name = debug_name; callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu); - rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR, + rc = bind_ipi_to_irqhandler(xh_default, XEN_CALL_FUNCTION_SINGLE_VECTOR, cpu, xen_call_function_single_interrupt, IRQF_PERCPU|IRQF_NOBALANCING, @@ -155,7 +155,7 @@ void __init xen_smp_cpus_done(unsigned int max_cpus) void xen_smp_send_reschedule(int cpu) { - xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR); + xen_send_IPI_one(xh_default, cpu, XEN_RESCHEDULE_VECTOR); } static void __xen_send_IPI_mask(const struct cpumask *mask, @@ -164,7 +164,7 @@ static void __xen_send_IPI_mask(const struct cpumask *mask, unsigned cpu; for_each_cpu_and(cpu, mask, cpu_online_mask) - xen_send_IPI_one(cpu, vector); + xen_send_IPI_one(xh_default, cpu, vector); } void xen_smp_send_call_function_ipi(const struct cpumask *mask) @@ -242,7 +242,7 @@ void xen_send_IPI_self(int vector) int xen_vector = xen_map_vector(vector); if (xen_vector >= 0) - xen_send_IPI_one(smp_processor_id(), xen_vector); + xen_send_IPI_one(xh_default, smp_processor_id(), xen_vector); } void xen_send_IPI_mask_allbutself(const struct cpumask *mask, @@ -259,7 +259,7 @@ void xen_send_IPI_mask_allbutself(const struct cpumask *mask, if (this_cpu == cpu) continue; - xen_send_IPI_one(cpu, xen_vector); + xen_send_IPI_one(xh_default, cpu, xen_vector); } } diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c index f4ea9eac8b6a..f8292be25d52 100644 --- a/arch/x86/xen/smp_pv.c +++ b/arch/x86/xen/smp_pv.c @@ -116,7 +116,7 @@ int xen_smp_intr_init_pv(unsigned int cpu) char *callfunc_name, *pmu_name; callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu); - rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR, + rc = bind_ipi_to_irqhandler(xh_default, XEN_IRQ_WORK_VECTOR, cpu, xen_irq_work_interrupt, IRQF_PERCPU|IRQF_NOBALANCING, @@ -129,7 +129,7 @@ int xen_smp_intr_init_pv(unsigned int cpu) if (is_xen_pmu(cpu)) { pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu); - rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu, + rc = bind_virq_to_irqhandler(xh_default, VIRQ_XENPMU, cpu, xen_pmu_irq_handler, IRQF_PERCPU|IRQF_NOBALANCING, pmu_name, NULL); diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 217bc4de07ee..2f7ff3272d5d 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -340,11 +340,12 @@ void xen_setup_timer(int cpu) snprintf(xevt->name, sizeof(xevt->name), "timer%d", cpu); - irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, + irq = bind_virq_to_irqhandler(xh_default, + VIRQ_TIMER, cpu, xen_timer_interrupt, IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER| IRQF_FORCE_RESUME|IRQF_EARLY_RESUME, xevt->name, NULL); - (void)xen_set_irq_priority(irq, XEN_IRQ_PRIORITY_MAX); + (void)xen_set_irq_priority(xh_default, irq, XEN_IRQ_PRIORITY_MAX); memcpy(evt, xen_clockevent, sizeof(*evt)); diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 96fd7edea7e9..4619808f1640 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -78,6 +78,7 @@ extern int xen_have_vcpu_info_placement; int xen_vcpu_setup(xenhost_t *xh, int cpu); void xen_vcpu_info_reset(xenhost_t *xh, int cpu); void xen_setup_vcpu_info_placement(void); +void xenhost_init_IRQ(void); #ifdef CONFIG_SMP void xen_smp_init(void); diff --git a/arch/x86/xen/xenhost.c b/arch/x86/xen/xenhost.c index 3d8ccef89dcd..3bbfd0654833 100644 --- a/arch/x86/xen/xenhost.c +++ b/arch/x86/xen/xenhost.c @@ -2,6 +2,7 @@ #include <linux/bug.h> #include <xen/xen.h> #include <xen/xenhost.h> +#include <xen/events.h> #include "xen-ops.h" /* @@ -84,3 +85,18 @@ void __xenhost_unregister(enum xenhost_type type) BUG(); } } + +void xenhost_init_IRQ(void) +{ + xenhost_t **xh; + /* + * xenhost_init_IRQ is called via x86_init.irq.intr_init(). + * For xenhost_r1 and xenhost_r2, the underlying state is + * ready so we can go ahead and init both the variants. + * + * xenhost_r0, might be implemented via a loadable module + * so that would do this initialization explicitly. + */ + for_each_xenhost(xh) + xen_init_IRQ(*xh); +} diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index a4bc74e72c39..beea4272cfd3 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -228,7 +228,7 @@ static int xen_blkif_map(struct xen_blkif_ring *ring, grant_ref_t *gref, BUG(); } - err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn, + err = bind_interdomain_evtchn_to_irqhandler(xh_default, blkif->domid, evtchn, xen_blkif_be_int, 0, "blkif-backend", ring); if (err < 0) { diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 0ed4b200fa58..a06716424023 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1700,7 +1700,7 @@ static int setup_blkring(struct xenbus_device *dev, if (err) goto fail; - err = bind_evtchn_to_irqhandler(rinfo->evtchn, blkif_interrupt, 0, + err = bind_evtchn_to_irqhandler(xh_default, rinfo->evtchn, blkif_interrupt, 0, "blkif", rinfo); if (err <= 0) { xenbus_dev_fatal(dev, err, diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 24bc5c5d876f..47c6e499fe31 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -435,7 +435,7 @@ static int xenkbd_connect_backend(struct xenbus_device *dev, ret = xenbus_alloc_evtchn(dev, &evtchn); if (ret) goto error_grant; - ret = bind_evtchn_to_irqhandler(evtchn, input_handler, + ret = bind_evtchn_to_irqhandler(xh_default, evtchn, input_handler, 0, dev->devicetype, info); if (ret < 0) { xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 182d6770f102..53d4e6351f1e 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -588,7 +588,7 @@ int xenvif_connect_ctrl(struct xenvif *vif, grant_ref_t ring_ref, shared = (struct xen_netif_ctrl_sring *)addr; BACK_RING_INIT(&vif->ctrl, shared, XEN_PAGE_SIZE); - err = bind_interdomain_evtchn_to_irq(vif->domid, evtchn); + err = bind_interdomain_evtchn_to_irq(xh_default, vif->domid, evtchn); if (err < 0) goto err_unmap; @@ -646,7 +646,7 @@ int xenvif_connect_data(struct xenvif_queue *queue, if (tx_evtchn == rx_evtchn) { /* feature-split-event-channels == 0 */ - err = bind_interdomain_evtchn_to_irqhandler( + err = bind_interdomain_evtchn_to_irqhandler(xh_default, queue->vif->domid, tx_evtchn, xenvif_interrupt, 0, queue->name, queue); if (err < 0) @@ -657,7 +657,7 @@ int xenvif_connect_data(struct xenvif_queue *queue, /* feature-split-event-channels == 1 */ snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name), "%s-tx", queue->name); - err = bind_interdomain_evtchn_to_irqhandler( + err = bind_interdomain_evtchn_to_irqhandler(xh_default, queue->vif->domid, tx_evtchn, xenvif_tx_interrupt, 0, queue->tx_irq_name, queue); if (err < 0) @@ -667,7 +667,7 @@ int xenvif_connect_data(struct xenvif_queue *queue, snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name), "%s-rx", queue->name); - err = bind_interdomain_evtchn_to_irqhandler( + err = bind_interdomain_evtchn_to_irqhandler(xh_default, queue->vif->domid, rx_evtchn, xenvif_rx_interrupt, 0, queue->rx_irq_name, queue); if (err < 0) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index c914c24f880b..1cd0a2d2ba54 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1468,7 +1468,7 @@ static int setup_netfront_single(struct netfront_queue *queue) if (err < 0) goto fail; - err = bind_evtchn_to_irqhandler(queue->tx_evtchn, + err = bind_evtchn_to_irqhandler(xh_default, queue->tx_evtchn, xennet_interrupt, 0, queue->info->netdev->name, queue); if (err < 0) @@ -1498,7 +1498,7 @@ static int setup_netfront_split(struct netfront_queue *queue) snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name), "%s-tx", queue->name); - err = bind_evtchn_to_irqhandler(queue->tx_evtchn, + err = bind_evtchn_to_irqhandler(xh_default, queue->tx_evtchn, xennet_tx_interrupt, 0, queue->tx_irq_name, queue); if (err < 0) @@ -1507,7 +1507,7 @@ static int setup_netfront_split(struct netfront_queue *queue) snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name), "%s-rx", queue->name); - err = bind_evtchn_to_irqhandler(queue->rx_evtchn, + err = bind_evtchn_to_irqhandler(xh_default, queue->rx_evtchn, xennet_rx_interrupt, 0, queue->rx_irq_name, queue); if (err < 0) diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index eba6e33147a2..f894290e8b3a 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -800,7 +800,7 @@ static int pcifront_publish_info(struct pcifront_device *pdev) if (err) goto out; - err = bind_evtchn_to_irqhandler(pdev->evtchn, pcifront_handler_aer, + err = bind_evtchn_to_irqhandler(xh_default, pdev->evtchn, pcifront_handler_aer, 0, "pcifront", pdev); if (err < 0) diff --git a/drivers/xen/acpi.c b/drivers/xen/acpi.c index 6893c79fd2a1..a959fce175f8 100644 --- a/drivers/xen/acpi.c +++ b/drivers/xen/acpi.c @@ -30,6 +30,8 @@ * IN THE SOFTWARE. */ +#include <linux/types.h> +#include <xen/interface/xen.h> #include <xen/acpi.h> #include <xen/interface/platform.h> #include <asm/xen/hypercall.h> diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index ceb5048de9a7..5ef4d6ad920d 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -62,11 +62,11 @@ #include <asm/pgtable.h> #include <asm/tlb.h> +#include <xen/interface/xen.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> #include <xen/xen.h> -#include <xen/interface/xen.h> #include <xen/interface/memory.h> #include <xen/balloon.h> #include <xen/features.h> diff --git a/drivers/xen/events/Makefile b/drivers/xen/events/Makefile index 62be55cd981d..08179fe04612 100644 --- a/drivers/xen/events/Makefile +++ b/drivers/xen/events/Makefile @@ -2,4 +2,3 @@ obj-y += events.o events-y += events_base.o events-y += events_2l.o -events-y += events_fifo.o diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c index f09dbe4e9c33..c69d7a5b3dff 100644 --- a/drivers/xen/events/events_2l.c +++ b/drivers/xen/events/events_2l.c @@ -40,50 +40,52 @@ #define EVTCHN_MASK_SIZE (EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD) -static DEFINE_PER_CPU(xen_ulong_t [EVTCHN_MASK_SIZE], cpu_evtchn_mask); +static DEFINE_PER_CPU(xen_ulong_t [2][EVTCHN_MASK_SIZE], cpu_evtchn_mask); -static unsigned evtchn_2l_max_channels(void) +static unsigned evtchn_2l_max_channels(xenhost_t *xh) { return EVTCHN_2L_NR_CHANNELS; } static void evtchn_2l_bind_to_cpu(struct irq_info *info, unsigned cpu) { - clear_bit(info->evtchn, BM(per_cpu(cpu_evtchn_mask, info->cpu))); - set_bit(info->evtchn, BM(per_cpu(cpu_evtchn_mask, cpu))); + clear_bit(info->evtchn, + BM(per_cpu(cpu_evtchn_mask, info->cpu))[info->xh - xenhosts]); + set_bit(info->evtchn, + BM(per_cpu(cpu_evtchn_mask, cpu))[info->xh - xenhosts]); } -static void evtchn_2l_clear_pending(unsigned port) +static void evtchn_2l_clear_pending(xenhost_t *xh, unsigned port) { struct shared_info *s = xh_default->HYPERVISOR_shared_info; sync_clear_bit(port, BM(&s->evtchn_pending[0])); } -static void evtchn_2l_set_pending(unsigned port) +static void evtchn_2l_set_pending(xenhost_t *xh, unsigned port) { struct shared_info *s = xh_default->HYPERVISOR_shared_info; sync_set_bit(port, BM(&s->evtchn_pending[0])); } -static bool evtchn_2l_is_pending(unsigned port) +static bool evtchn_2l_is_pending(xenhost_t *xh, unsigned port) { - struct shared_info *s = xh_default->HYPERVISOR_shared_info; + struct shared_info *s = xh->HYPERVISOR_shared_info; return sync_test_bit(port, BM(&s->evtchn_pending[0])); } -static bool evtchn_2l_test_and_set_mask(unsigned port) +static bool evtchn_2l_test_and_set_mask(xenhost_t *xh, unsigned port) { - struct shared_info *s = xh_default->HYPERVISOR_shared_info; + struct shared_info *s = xh->HYPERVISOR_shared_info; return sync_test_and_set_bit(port, BM(&s->evtchn_mask[0])); } -static void evtchn_2l_mask(unsigned port) +static void evtchn_2l_mask(xenhost_t *xh, unsigned port) { struct shared_info *s = xh_default->HYPERVISOR_shared_info; sync_set_bit(port, BM(&s->evtchn_mask[0])); } -static void evtchn_2l_unmask(unsigned port) +static void evtchn_2l_unmask(xenhost_t *xh, unsigned port) { struct shared_info *s = xh_default->HYPERVISOR_shared_info; unsigned int cpu = get_cpu(); @@ -91,7 +93,7 @@ static void evtchn_2l_unmask(unsigned port) BUG_ON(!irqs_disabled()); - if (unlikely((cpu != cpu_from_evtchn(port)))) + if (unlikely((cpu != cpu_from_evtchn(xh, port)))) do_hypercall = 1; else { /* @@ -116,9 +118,9 @@ static void evtchn_2l_unmask(unsigned port) * their own implementation of irq_enable). */ if (do_hypercall) { struct evtchn_unmask unmask = { .port = port }; - (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); + (void)hypervisor_event_channel_op(xh, EVTCHNOP_unmask, &unmask); } else { - struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); + struct vcpu_info *vcpu_info = xh->xen_vcpu[cpu]; /* * The following is basically the equivalent of @@ -134,8 +136,8 @@ static void evtchn_2l_unmask(unsigned port) put_cpu(); } -static DEFINE_PER_CPU(unsigned int, current_word_idx); -static DEFINE_PER_CPU(unsigned int, current_bit_idx); +static DEFINE_PER_CPU(unsigned int [2], current_word_idx); +static DEFINE_PER_CPU(unsigned int [2], current_bit_idx); /* * Mask out the i least significant bits of w @@ -143,11 +145,12 @@ static DEFINE_PER_CPU(unsigned int, current_bit_idx); #define MASK_LSBS(w, i) (w & ((~((xen_ulong_t)0UL)) << i)) static inline xen_ulong_t active_evtchns(unsigned int cpu, + xenhost_t *xh, struct shared_info *sh, unsigned int idx) { return sh->evtchn_pending[idx] & - per_cpu(cpu_evtchn_mask, cpu)[idx] & + per_cpu(cpu_evtchn_mask, cpu)[xh - xenhosts][idx] & ~sh->evtchn_mask[idx]; } @@ -159,7 +162,7 @@ static inline xen_ulong_t active_evtchns(unsigned int cpu, * a bitset of words which contain pending event bits. The second * level is a bitset of pending events themselves. */ -static void evtchn_2l_handle_events(unsigned cpu) +static void evtchn_2l_handle_events(xenhost_t *xh, unsigned cpu) { int irq; xen_ulong_t pending_words; @@ -167,8 +170,8 @@ static void evtchn_2l_handle_events(unsigned cpu) int start_word_idx, start_bit_idx; int word_idx, bit_idx; int i; - struct shared_info *s = xh_default->HYPERVISOR_shared_info; - struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); + struct shared_info *s = xh->HYPERVISOR_shared_info; + struct vcpu_info *vcpu_info = xh->xen_vcpu[cpu]; /* Timer interrupt has highest priority. */ irq = irq_from_virq(cpu, VIRQ_TIMER); @@ -176,7 +179,7 @@ static void evtchn_2l_handle_events(unsigned cpu) unsigned int evtchn = evtchn_from_irq(irq); word_idx = evtchn / BITS_PER_LONG; bit_idx = evtchn % BITS_PER_LONG; - if (active_evtchns(cpu, s, word_idx) & (1ULL << bit_idx)) + if (active_evtchns(cpu, xh, s, word_idx) & (1ULL << bit_idx)) generic_handle_irq(irq); } @@ -187,8 +190,8 @@ static void evtchn_2l_handle_events(unsigned cpu) */ pending_words = xchg_xen_ulong(&vcpu_info->evtchn_pending_sel, 0); - start_word_idx = __this_cpu_read(current_word_idx); - start_bit_idx = __this_cpu_read(current_bit_idx); + start_word_idx = __this_cpu_read(current_word_idx[xh - xenhosts]); + start_bit_idx = __this_cpu_read(current_bit_idx[xh - xenhosts]); word_idx = start_word_idx; @@ -207,7 +210,7 @@ static void evtchn_2l_handle_events(unsigned cpu) } word_idx = EVTCHN_FIRST_BIT(words); - pending_bits = active_evtchns(cpu, s, word_idx); + pending_bits = active_evtchns(cpu, xh, s, word_idx); bit_idx = 0; /* usually scan entire word from start */ /* * We scan the starting word in two parts. @@ -240,7 +243,7 @@ static void evtchn_2l_handle_events(unsigned cpu) /* Process port. */ port = (word_idx * BITS_PER_EVTCHN_WORD) + bit_idx; - irq = get_evtchn_to_irq(port); + irq = get_evtchn_to_irq(xh, port); if (irq != -1) generic_handle_irq(irq); @@ -248,10 +251,10 @@ static void evtchn_2l_handle_events(unsigned cpu) bit_idx = (bit_idx + 1) % BITS_PER_EVTCHN_WORD; /* Next caller starts at last processed + 1 */ - __this_cpu_write(current_word_idx, + __this_cpu_write(current_word_idx[xh - xenhosts], bit_idx ? word_idx : (word_idx+1) % BITS_PER_EVTCHN_WORD); - __this_cpu_write(current_bit_idx, bit_idx); + __this_cpu_write(current_bit_idx[xh - xenhosts], bit_idx); } while (bit_idx != 0); /* Scan start_l1i twice; all others once. */ @@ -266,78 +269,81 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) { struct shared_info *sh = xh_default->HYPERVISOR_shared_info; int cpu = smp_processor_id(); - xen_ulong_t *cpu_evtchn = per_cpu(cpu_evtchn_mask, cpu); + xen_ulong_t *cpu_evtchn; int i; unsigned long flags; static DEFINE_SPINLOCK(debug_lock); struct vcpu_info *v; + xenhost_t **xh; spin_lock_irqsave(&debug_lock, flags); printk("\nvcpu %d\n ", cpu); - for_each_online_cpu(i) { - int pending; - v = per_cpu(xen_vcpu, i); - pending = (get_irq_regs() && i == cpu) - ? xen_irqs_disabled(get_irq_regs()) - : v->evtchn_upcall_mask; - printk("%d: masked=%d pending=%d event_sel %0*"PRI_xen_ulong"\n ", i, - pending, v->evtchn_upcall_pending, - (int)(sizeof(v->evtchn_pending_sel)*2), - v->evtchn_pending_sel); - } - v = per_cpu(xen_vcpu, cpu); + for_each_xenhost(xh) { + cpu_evtchn = per_cpu(cpu_evtchn_mask, cpu)[(*xh) - xenhosts]; + for_each_online_cpu(i) { + int pending; + v = (*xh)->xen_vcpu[i]; + pending = (get_irq_regs() && i == cpu) + ? xen_irqs_disabled(get_irq_regs()) + : v->evtchn_upcall_mask; + printk("%d: masked=%d pending=%d event_sel %0*"PRI_xen_ulong"\n ", i, + pending, v->evtchn_upcall_pending, + (int)(sizeof(v->evtchn_pending_sel)*2), + v->evtchn_pending_sel); + } + v = (*xh)->xen_vcpu[cpu]; - printk("\npending:\n "); - for (i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--) - printk("%0*"PRI_xen_ulong"%s", - (int)sizeof(sh->evtchn_pending[0])*2, - sh->evtchn_pending[i], - i % 8 == 0 ? "\n " : " "); - printk("\nglobal mask:\n "); - for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) - printk("%0*"PRI_xen_ulong"%s", - (int)(sizeof(sh->evtchn_mask[0])*2), - sh->evtchn_mask[i], - i % 8 == 0 ? "\n " : " "); + printk("\npending:\n "); + for (i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--) + printk("%0*"PRI_xen_ulong"%s", + (int)sizeof(sh->evtchn_pending[0])*2, + sh->evtchn_pending[i], + i % 8 == 0 ? "\n " : " "); + printk("\nglobal mask:\n "); + for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) + printk("%0*"PRI_xen_ulong"%s", + (int)(sizeof(sh->evtchn_mask[0])*2), + sh->evtchn_mask[i], + i % 8 == 0 ? "\n " : " "); - printk("\nglobally unmasked:\n "); - for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) - printk("%0*"PRI_xen_ulong"%s", - (int)(sizeof(sh->evtchn_mask[0])*2), - sh->evtchn_pending[i] & ~sh->evtchn_mask[i], - i % 8 == 0 ? "\n " : " "); + printk("\nglobally unmasked:\n "); + for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) + printk("%0*"PRI_xen_ulong"%s", + (int)(sizeof(sh->evtchn_mask[0])*2), + sh->evtchn_pending[i] & ~sh->evtchn_mask[i], + i % 8 == 0 ? "\n " : " "); + printk("\nlocal cpu%d mask:\n ", cpu); + for (i = (EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD)-1; i >= 0; i--) + printk("%0*"PRI_xen_ulong"%s", (int)(sizeof(cpu_evtchn[0])*2), + cpu_evtchn[i], + i % 8 == 0 ? "\n " : " "); - printk("\nlocal cpu%d mask:\n ", cpu); - for (i = (EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD)-1; i >= 0; i--) - printk("%0*"PRI_xen_ulong"%s", (int)(sizeof(cpu_evtchn[0])*2), - cpu_evtchn[i], - i % 8 == 0 ? "\n " : " "); + printk("\nlocally unmasked:\n "); + for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) { + xen_ulong_t pending = sh->evtchn_pending[i] + & ~sh->evtchn_mask[i] + & cpu_evtchn[i]; + printk("%0*"PRI_xen_ulong"%s", + (int)(sizeof(sh->evtchn_mask[0])*2), + pending, i % 8 == 0 ? "\n " : " "); + } - printk("\nlocally unmasked:\n "); - for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) { - xen_ulong_t pending = sh->evtchn_pending[i] - & ~sh->evtchn_mask[i] - & cpu_evtchn[i]; - printk("%0*"PRI_xen_ulong"%s", - (int)(sizeof(sh->evtchn_mask[0])*2), - pending, i % 8 == 0 ? "\n " : " "); - } - - printk("\npending list:\n"); - for (i = 0; i < EVTCHN_2L_NR_CHANNELS; i++) { - if (sync_test_bit(i, BM(sh->evtchn_pending))) { - int word_idx = i / BITS_PER_EVTCHN_WORD; - printk(" %d: event %d -> irq %d%s%s%s\n", - cpu_from_evtchn(i), i, - get_evtchn_to_irq(i), - sync_test_bit(word_idx, BM(&v->evtchn_pending_sel)) - ? "" : " l2-clear", - !sync_test_bit(i, BM(sh->evtchn_mask)) - ? "" : " globally-masked", - sync_test_bit(i, BM(cpu_evtchn)) - ? "" : " locally-masked"); + printk("\npending list:\n"); + for (i = 0; i < EVTCHN_2L_NR_CHANNELS; i++) { + if (sync_test_bit(i, BM(sh->evtchn_pending))) { + int word_idx = i / BITS_PER_EVTCHN_WORD; + printk(" %d: event %d -> irq %d%s%s%s\n", + cpu_from_evtchn(*xh, i), i, + get_evtchn_to_irq(*xh, i), + sync_test_bit(word_idx, BM(&v->evtchn_pending_sel)) + ? "" : " l2-clear", + !sync_test_bit(i, BM(sh->evtchn_mask)) + ? "" : " globally-masked", + sync_test_bit(i, BM(cpu_evtchn)) + ? "" : " locally-masked"); + } } } @@ -346,12 +352,12 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void evtchn_2l_resume(void) +static void evtchn_2l_resume(xenhost_t *xh) { int i; for_each_online_cpu(i) - memset(per_cpu(cpu_evtchn_mask, i), 0, sizeof(xen_ulong_t) * + memset(per_cpu(cpu_evtchn_mask, i)[xh - xenhosts], 0, sizeof(xen_ulong_t) * EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD); } @@ -369,8 +375,8 @@ static const struct evtchn_ops evtchn_ops_2l = { .resume = evtchn_2l_resume, }; -void __init xen_evtchn_2l_init(void) +void xen_evtchn_2l_init(xenhost_t *xh) { pr_info("Using 2-level ABI\n"); - evtchn_ops = &evtchn_ops_2l; + xh->evtchn_ops = &evtchn_ops_2l; } diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index ae497876fe41..99b6b2c57d23 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -77,15 +77,14 @@ static DEFINE_PER_CPU(int [NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1}; /* IRQ <-> IPI mapping */ static DEFINE_PER_CPU(int [XEN_NR_IPIS], ipi_to_irq) = {[0 ... XEN_NR_IPIS-1] = -1}; -int **evtchn_to_irq; #ifdef CONFIG_X86 static unsigned long *pirq_eoi_map; #endif static bool (*pirq_needs_eoi)(unsigned irq); -#define EVTCHN_ROW(e) (e / (PAGE_SIZE/sizeof(**evtchn_to_irq))) -#define EVTCHN_COL(e) (e % (PAGE_SIZE/sizeof(**evtchn_to_irq))) -#define EVTCHN_PER_ROW (PAGE_SIZE / sizeof(**evtchn_to_irq)) +#define EVTCHN_ROW(xh, e) (e / (PAGE_SIZE/sizeof(**((xh)->evtchn_to_irq)))) +#define EVTCHN_COL(xh, e) (e % (PAGE_SIZE/sizeof(**((xh)->evtchn_to_irq)))) +#define EVTCHN_PER_ROW(xh) (PAGE_SIZE / sizeof(**((xh)->evtchn_to_irq))) /* Xen will never allocate port zero for any purpose. */ #define VALID_EVTCHN(chn) ((chn) != 0) @@ -96,59 +95,62 @@ static struct irq_chip xen_pirq_chip; static void enable_dynirq(struct irq_data *data); static void disable_dynirq(struct irq_data *data); -static void clear_evtchn_to_irq_row(unsigned row) +static void clear_evtchn_to_irq_row(xenhost_t *xh, unsigned row) { unsigned col; - for (col = 0; col < EVTCHN_PER_ROW; col++) - evtchn_to_irq[row][col] = -1; + for (col = 0; col < EVTCHN_PER_ROW(xh); col++) + xh->evtchn_to_irq[row][col] = -1; } static void clear_evtchn_to_irq_all(void) { unsigned row; + xenhost_t **xh; - for (row = 0; row < EVTCHN_ROW(xen_evtchn_max_channels()); row++) { - if (evtchn_to_irq[row] == NULL) - continue; - clear_evtchn_to_irq_row(row); + for_each_xenhost(xh) { + for (row = 0; row < EVTCHN_ROW(*xh, xen_evtchn_max_channels(*xh)); row++) { + if ((*xh)->evtchn_to_irq[row] == NULL) + continue; + clear_evtchn_to_irq_row(*xh, row); + } } } -static int set_evtchn_to_irq(unsigned evtchn, unsigned irq) +static int set_evtchn_to_irq(xenhost_t *xh, unsigned evtchn, unsigned irq) { unsigned row; unsigned col; - if (evtchn >= xen_evtchn_max_channels()) + if (evtchn >= xen_evtchn_max_channels(xh)) return -EINVAL; - row = EVTCHN_ROW(evtchn); - col = EVTCHN_COL(evtchn); + row = EVTCHN_ROW(xh, evtchn); + col = EVTCHN_COL(xh, evtchn); - if (evtchn_to_irq[row] == NULL) { + if (xh->evtchn_to_irq[row] == NULL) { /* Unallocated irq entries return -1 anyway */ if (irq == -1) return 0; - evtchn_to_irq[row] = (int *)get_zeroed_page(GFP_KERNEL); - if (evtchn_to_irq[row] == NULL) + xh->evtchn_to_irq[row] = (int *)get_zeroed_page(GFP_KERNEL); + if (xh->evtchn_to_irq[row] == NULL) return -ENOMEM; - clear_evtchn_to_irq_row(row); + clear_evtchn_to_irq_row(xh, row); } - evtchn_to_irq[row][col] = irq; + xh->evtchn_to_irq[row][col] = irq; return 0; } -int get_evtchn_to_irq(unsigned evtchn) +int get_evtchn_to_irq(xenhost_t *xh, unsigned evtchn) { - if (evtchn >= xen_evtchn_max_channels()) + if (evtchn >= xen_evtchn_max_channels(xh)) return -1; - if (evtchn_to_irq[EVTCHN_ROW(evtchn)] == NULL) + if (xh->evtchn_to_irq[EVTCHN_ROW(xh, evtchn)] == NULL) return -1; - return evtchn_to_irq[EVTCHN_ROW(evtchn)][EVTCHN_COL(evtchn)]; + return xh->evtchn_to_irq[EVTCHN_ROW(xh, evtchn)][EVTCHN_COL(xh, evtchn)]; } /* Get info for IRQ */ @@ -159,6 +161,7 @@ struct irq_info *info_for_irq(unsigned irq) /* Constructors for packed IRQ information. */ static int xen_irq_info_common_setup(struct irq_info *info, + xenhost_t *xh, unsigned irq, enum xen_irq_type type, unsigned evtchn, @@ -173,7 +176,7 @@ static int xen_irq_info_common_setup(struct irq_info *info, info->evtchn = evtchn; info->cpu = cpu; - ret = set_evtchn_to_irq(evtchn, irq); + ret = set_evtchn_to_irq(xh, evtchn, irq); if (ret < 0) return ret; @@ -182,29 +185,34 @@ static int xen_irq_info_common_setup(struct irq_info *info, return xen_evtchn_port_setup(info); } -static int xen_irq_info_evtchn_setup(unsigned irq, +static int xen_irq_info_evtchn_setup(xenhost_t *xh, + unsigned irq, unsigned evtchn) { struct irq_info *info = info_for_irq(irq); - return xen_irq_info_common_setup(info, irq, IRQT_EVTCHN, evtchn, 0); + return xen_irq_info_common_setup(info, xh, irq, IRQT_EVTCHN, evtchn, 0); } -static int xen_irq_info_ipi_setup(unsigned cpu, +static int xen_irq_info_ipi_setup(xenhost_t *xh, + unsigned cpu, unsigned irq, unsigned evtchn, enum ipi_vector ipi) { struct irq_info *info = info_for_irq(irq); + BUG_ON(xh->type != xenhost_r1); + info->u.ipi = ipi; per_cpu(ipi_to_irq, cpu)[ipi] = irq; - return xen_irq_info_common_setup(info, irq, IRQT_IPI, evtchn, 0); + return xen_irq_info_common_setup(info, xh, irq, IRQT_IPI, evtchn, 0); } -static int xen_irq_info_virq_setup(unsigned cpu, +static int xen_irq_info_virq_setup(xenhost_t *xh, + unsigned cpu, unsigned irq, unsigned evtchn, unsigned virq) @@ -215,10 +223,11 @@ static int xen_irq_info_virq_setup(unsigned cpu, per_cpu(virq_to_irq, cpu)[virq] = irq; - return xen_irq_info_common_setup(info, irq, IRQT_VIRQ, evtchn, 0); + return xen_irq_info_common_setup(info, xh, irq, IRQT_VIRQ, evtchn, 0); } -static int xen_irq_info_pirq_setup(unsigned irq, +static int xen_irq_info_pirq_setup(xenhost_t *xh, + unsigned irq, unsigned evtchn, unsigned pirq, unsigned gsi, @@ -232,12 +241,12 @@ static int xen_irq_info_pirq_setup(unsigned irq, info->u.pirq.domid = domid; info->u.pirq.flags = flags; - return xen_irq_info_common_setup(info, irq, IRQT_PIRQ, evtchn, 0); + return xen_irq_info_common_setup(info, xh, irq, IRQT_PIRQ, evtchn, 0); } static void xen_irq_info_cleanup(struct irq_info *info) { - set_evtchn_to_irq(info->evtchn, -1); + set_evtchn_to_irq(info->xh, info->evtchn, -1); info->evtchn = 0; } @@ -252,9 +261,9 @@ unsigned int evtchn_from_irq(unsigned irq) return info_for_irq(irq)->evtchn; } -unsigned irq_from_evtchn(unsigned int evtchn) +unsigned irq_from_evtchn(xenhost_t *xh, unsigned int evtchn) { - return get_evtchn_to_irq(evtchn); + return get_evtchn_to_irq(xh, evtchn); } EXPORT_SYMBOL_GPL(irq_from_evtchn); @@ -303,9 +312,9 @@ unsigned cpu_from_irq(unsigned irq) return info_for_irq(irq)->cpu; } -unsigned int cpu_from_evtchn(unsigned int evtchn) +unsigned int cpu_from_evtchn(xenhost_t *xh, unsigned int evtchn) { - int irq = get_evtchn_to_irq(evtchn); + int irq = get_evtchn_to_irq(xh, evtchn); unsigned ret = 0; if (irq != -1) @@ -329,9 +338,9 @@ static bool pirq_needs_eoi_flag(unsigned irq) return info->u.pirq.flags & PIRQ_NEEDS_EOI; } -static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) +static void bind_evtchn_to_cpu(xenhost_t *xh, unsigned int chn, unsigned int cpu) { - int irq = get_evtchn_to_irq(chn); + int irq = get_evtchn_to_irq(xh, chn); struct irq_info *info = info_for_irq(irq); BUG_ON(irq == -1); @@ -356,11 +365,11 @@ void notify_remote_via_irq(int irq) int evtchn = evtchn_from_irq(irq); if (VALID_EVTCHN(evtchn)) - notify_remote_via_evtchn(evtchn); + notify_remote_via_evtchn(info_for_irq(irq)->xh, evtchn); } EXPORT_SYMBOL_GPL(notify_remote_via_irq); -static void xen_irq_init(unsigned irq) +static void xen_irq_init(xenhost_t *xh, unsigned irq) { struct irq_info *info; #ifdef CONFIG_SMP @@ -374,31 +383,32 @@ static void xen_irq_init(unsigned irq) info->type = IRQT_UNBOUND; info->refcnt = -1; + info->xh = xh; irq_set_handler_data(irq, info); list_add_tail(&info->list, &xen_irq_list_head); } -static int __must_check xen_allocate_irqs_dynamic(int nvec) +static int __must_check xen_allocate_irqs_dynamic(xenhost_t *xh, int nvec) { int i, irq = irq_alloc_descs(-1, 0, nvec, -1); if (irq >= 0) { for (i = 0; i < nvec; i++) - xen_irq_init(irq + i); + xen_irq_init(xh, irq + i); } return irq; } -static inline int __must_check xen_allocate_irq_dynamic(void) +static inline int __must_check xen_allocate_irq_dynamic(xenhost_t *xh) { - return xen_allocate_irqs_dynamic(1); + return xen_allocate_irqs_dynamic(xh, 1); } -static int __must_check xen_allocate_irq_gsi(unsigned gsi) +static int __must_check xen_allocate_irq_gsi(xenhost_t *xh, unsigned gsi) { int irq; @@ -409,7 +419,7 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi) * space. */ if (xen_pv_domain() && !xen_initial_domain()) - return xen_allocate_irq_dynamic(); + return xen_allocate_irq_dynamic(xh); /* Legacy IRQ descriptors are already allocated by the arch. */ if (gsi < nr_legacy_irqs()) @@ -417,7 +427,7 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi) else irq = irq_alloc_desc_at(gsi, -1); - xen_irq_init(irq); + xen_irq_init(xh, irq); return irq; } @@ -444,12 +454,12 @@ static void xen_free_irq(unsigned irq) irq_free_desc(irq); } -static void xen_evtchn_close(unsigned int port) +static void xen_evtchn_close(xenhost_t *xh, unsigned int port) { struct evtchn_close close; close.port = port; - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) + if (hypervisor_event_channel_op(xh, EVTCHNOP_close, &close) != 0) BUG(); } @@ -473,6 +483,7 @@ static void eoi_pirq(struct irq_data *data) { int evtchn = evtchn_from_irq(data->irq); struct physdev_eoi eoi = { .irq = pirq_from_irq(data->irq) }; + xenhost_t *xh = info_for_irq(data->irq)->xh; int rc = 0; if (!VALID_EVTCHN(evtchn)) @@ -480,16 +491,16 @@ static void eoi_pirq(struct irq_data *data) if (unlikely(irqd_is_setaffinity_pending(data)) && likely(!irqd_irq_disabled(data))) { - int masked = test_and_set_mask(evtchn); + int masked = test_and_set_mask(xh, evtchn); - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); irq_move_masked_irq(data); if (!masked) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); } else - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); if (pirq_needs_eoi(data->irq)) { rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi); @@ -519,7 +530,7 @@ static unsigned int __startup_pirq(unsigned int irq) /* NB. We are happy to share unless we are probing. */ bind_pirq.flags = info->u.pirq.flags & PIRQ_SHAREABLE ? BIND_PIRQ__WILL_SHARE : 0; - rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq); + rc = hypervisor_event_channel_op(info->xh, EVTCHNOP_bind_pirq, &bind_pirq); if (rc != 0) { pr_warn("Failed to obtain physical IRQ %d\n", irq); return 0; @@ -528,26 +539,26 @@ static unsigned int __startup_pirq(unsigned int irq) pirq_query_unmask(irq); - rc = set_evtchn_to_irq(evtchn, irq); + rc = set_evtchn_to_irq(info->xh, evtchn, irq); if (rc) goto err; info->evtchn = evtchn; - bind_evtchn_to_cpu(evtchn, 0); + bind_evtchn_to_cpu(info->xh, evtchn, 0); rc = xen_evtchn_port_setup(info); if (rc) goto err; out: - unmask_evtchn(evtchn); + unmask_evtchn(info->xh, evtchn); eoi_pirq(irq_get_irq_data(irq)); return 0; err: pr_err("irq%d: Failed to set port to irq mapping (%d)\n", irq, rc); - xen_evtchn_close(evtchn); + xen_evtchn_close(info->xh, evtchn); return 0; } @@ -567,8 +578,8 @@ static void shutdown_pirq(struct irq_data *data) if (!VALID_EVTCHN(evtchn)) return; - mask_evtchn(evtchn); - xen_evtchn_close(evtchn); + mask_evtchn(info->xh, evtchn); + xen_evtchn_close(info->xh, evtchn); xen_irq_info_cleanup(info); } @@ -612,7 +623,7 @@ static void __unbind_from_irq(unsigned int irq) if (VALID_EVTCHN(evtchn)) { unsigned int cpu = cpu_from_irq(irq); - xen_evtchn_close(evtchn); + xen_evtchn_close(info->xh, evtchn); switch (type_from_irq(irq)) { case IRQT_VIRQ: @@ -641,13 +652,15 @@ static void __unbind_from_irq(unsigned int irq) * Shareable implies level triggered, not shareable implies edge * triggered here. */ -int xen_bind_pirq_gsi_to_irq(unsigned gsi, +int xen_bind_pirq_gsi_to_irq(xenhost_t *xh, unsigned gsi, unsigned pirq, int shareable, char *name) { int irq = -1; struct physdev_irq irq_op; int ret; + BUG_ON(xh->type != xenhost_r1); + mutex_lock(&irq_mapping_update_lock); irq = xen_irq_from_gsi(gsi); @@ -657,7 +670,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, goto out; } - irq = xen_allocate_irq_gsi(gsi); + irq = xen_allocate_irq_gsi(xh, gsi); if (irq < 0) goto out; @@ -668,13 +681,13 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, * driver provides a PCI bus that does the call to do exactly * this in the priv domain. */ if (xen_initial_domain() && - HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) { + hypervisor_physdev_op(xh, PHYSDEVOP_alloc_irq_vector, &irq_op)) { xen_free_irq(irq); irq = -ENOSPC; goto out; } - ret = xen_irq_info_pirq_setup(irq, 0, pirq, gsi, DOMID_SELF, + ret = xen_irq_info_pirq_setup(xh, irq, 0, pirq, gsi, DOMID_SELF, shareable ? PIRQ_SHAREABLE : 0); if (ret < 0) { __unbind_from_irq(irq); @@ -712,13 +725,13 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, } #ifdef CONFIG_PCI_MSI -int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) +int xen_allocate_pirq_msi(xenhost_t *xh, struct pci_dev *dev, struct msi_desc *msidesc) { int rc; struct physdev_get_free_pirq op_get_free_pirq; op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI; - rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); + rc = hypervisor_physdev_op(xh, PHYSDEVOP_get_free_pirq, &op_get_free_pirq); WARN_ONCE(rc == -ENOSYS, "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n"); @@ -726,21 +739,21 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) return rc ? -1 : op_get_free_pirq.pirq; } -int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, +int xen_bind_pirq_msi_to_irq(xenhost_t *xh, struct pci_dev *dev, struct msi_desc *msidesc, int pirq, int nvec, const char *name, domid_t domid) { int i, irq, ret; mutex_lock(&irq_mapping_update_lock); - irq = xen_allocate_irqs_dynamic(nvec); + irq = xen_allocate_irqs_dynamic(xh, nvec); if (irq < 0) goto out; for (i = 0; i < nvec; i++) { irq_set_chip_and_handler_name(irq + i, &xen_pirq_chip, handle_edge_irq, name); - ret = xen_irq_info_pirq_setup(irq + i, 0, pirq + i, 0, domid, + ret = xen_irq_info_pirq_setup(xh, irq + i, 0, pirq + i, 0, domid, i == 0 ? 0 : PIRQ_MSI_GROUP); if (ret < 0) goto error_irq; @@ -776,7 +789,7 @@ int xen_destroy_irq(int irq) if (xen_initial_domain() && !(info->u.pirq.flags & PIRQ_MSI_GROUP)) { unmap_irq.pirq = info->u.pirq.pirq; unmap_irq.domid = info->u.pirq.domid; - rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); + rc = hypervisor_physdev_op(info->xh, PHYSDEVOP_unmap_pirq, &unmap_irq); /* If another domain quits without making the pci_disable_msix * call, the Xen hypervisor takes care of freeing the PIRQs * (free_domain_pirqs). @@ -826,34 +839,34 @@ int xen_pirq_from_irq(unsigned irq) } EXPORT_SYMBOL_GPL(xen_pirq_from_irq); -int bind_evtchn_to_irq(unsigned int evtchn) +int bind_evtchn_to_irq(xenhost_t *xh, unsigned int evtchn) { int irq; int ret; - if (evtchn >= xen_evtchn_max_channels()) + if (evtchn >= xen_evtchn_max_channels(xh)) return -ENOMEM; mutex_lock(&irq_mapping_update_lock); - irq = get_evtchn_to_irq(evtchn); + irq = get_evtchn_to_irq(xh, evtchn); if (irq == -1) { - irq = xen_allocate_irq_dynamic(); + irq = xen_allocate_irq_dynamic(xh); if (irq < 0) goto out; irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, handle_edge_irq, "event"); - ret = xen_irq_info_evtchn_setup(irq, evtchn); + ret = xen_irq_info_evtchn_setup(xh, irq, evtchn); if (ret < 0) { __unbind_from_irq(irq); irq = ret; goto out; } /* New interdomain events are bound to VCPU 0. */ - bind_evtchn_to_cpu(evtchn, 0); + bind_evtchn_to_cpu(xh, evtchn, 0); } else { struct irq_info *info = info_for_irq(irq); WARN_ON(info == NULL || info->type != IRQT_EVTCHN); @@ -866,37 +879,39 @@ int bind_evtchn_to_irq(unsigned int evtchn) } EXPORT_SYMBOL_GPL(bind_evtchn_to_irq); -static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) +static int bind_ipi_to_irq(xenhost_t *xh, unsigned int ipi, unsigned int cpu) { struct evtchn_bind_ipi bind_ipi; int evtchn, irq; int ret; + BUG_ON(xh->type == xenhost_r2); + mutex_lock(&irq_mapping_update_lock); irq = per_cpu(ipi_to_irq, cpu)[ipi]; if (irq == -1) { - irq = xen_allocate_irq_dynamic(); + irq = xen_allocate_irq_dynamic(xh); if (irq < 0) goto out; irq_set_chip_and_handler_name(irq, &xen_percpu_chip, handle_percpu_irq, "ipi"); - bind_ipi.vcpu = xen_vcpu_nr(xh_default, cpu); - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, + bind_ipi.vcpu = xen_vcpu_nr(xh, cpu); + if (hypervisor_event_channel_op(xh, EVTCHNOP_bind_ipi, &bind_ipi) != 0) BUG(); evtchn = bind_ipi.port; - ret = xen_irq_info_ipi_setup(cpu, irq, evtchn, ipi); + ret = xen_irq_info_ipi_setup(xh, cpu, irq, evtchn, ipi); if (ret < 0) { __unbind_from_irq(irq); irq = ret; goto out; } - bind_evtchn_to_cpu(evtchn, cpu); + bind_evtchn_to_cpu(xh, evtchn, cpu); } else { struct irq_info *info = info_for_irq(irq); WARN_ON(info == NULL || info->type != IRQT_IPI); @@ -907,7 +922,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) return irq; } -int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, +int bind_interdomain_evtchn_to_irq(xenhost_t *xh, unsigned int remote_domain, unsigned int remote_port) { struct evtchn_bind_interdomain bind_interdomain; @@ -916,28 +931,28 @@ int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, bind_interdomain.remote_dom = remote_domain; bind_interdomain.remote_port = remote_port; - err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, + err = hypervisor_event_channel_op(xh, EVTCHNOP_bind_interdomain, &bind_interdomain); - return err ? : bind_evtchn_to_irq(bind_interdomain.local_port); + return err ? : bind_evtchn_to_irq(xh, bind_interdomain.local_port); } EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irq); -static int find_virq(unsigned int virq, unsigned int cpu) +static int find_virq(xenhost_t *xh, unsigned int virq, unsigned int cpu) { struct evtchn_status status; int port, rc = -ENOENT; memset(&status, 0, sizeof(status)); - for (port = 0; port < xen_evtchn_max_channels(); port++) { + for (port = 0; port < xen_evtchn_max_channels(xh); port++) { status.dom = DOMID_SELF; status.port = port; - rc = HYPERVISOR_event_channel_op(EVTCHNOP_status, &status); + rc = hypervisor_event_channel_op(xh, EVTCHNOP_status, &status); if (rc < 0) continue; if (status.status != EVTCHNSTAT_virq) continue; - if (status.u.virq == virq && status.vcpu == xen_vcpu_nr(xh_default, cpu)) { + if (status.u.virq == virq && status.vcpu == xen_vcpu_nr(xh, cpu)) { rc = port; break; } @@ -952,13 +967,13 @@ static int find_virq(unsigned int virq, unsigned int cpu) * hypervisor ABI. Use xen_evtchn_max_channels() for the maximum * supported. */ -unsigned xen_evtchn_nr_channels(void) +unsigned xen_evtchn_nr_channels(xenhost_t *xh) { - return evtchn_ops->nr_channels(); + return evtchn_ops->nr_channels(xh); } EXPORT_SYMBOL_GPL(xen_evtchn_nr_channels); -int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu) +int bind_virq_to_irq(xenhost_t *xh, unsigned int virq, unsigned int cpu, bool percpu) { struct evtchn_bind_virq bind_virq; int evtchn, irq, ret; @@ -968,7 +983,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu) irq = per_cpu(virq_to_irq, cpu)[virq]; if (irq == -1) { - irq = xen_allocate_irq_dynamic(); + irq = xen_allocate_irq_dynamic(xh); if (irq < 0) goto out; @@ -980,26 +995,26 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu) handle_edge_irq, "virq"); bind_virq.virq = virq; - bind_virq.vcpu = xen_vcpu_nr(xh_default, cpu); - ret = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, + bind_virq.vcpu = xen_vcpu_nr(xh, cpu); + ret = hypervisor_event_channel_op(xh, EVTCHNOP_bind_virq, &bind_virq); if (ret == 0) evtchn = bind_virq.port; else { if (ret == -EEXIST) - ret = find_virq(virq, cpu); + ret = find_virq(xh, virq, cpu); BUG_ON(ret < 0); evtchn = ret; } - ret = xen_irq_info_virq_setup(cpu, irq, evtchn, virq); + ret = xen_irq_info_virq_setup(xh, cpu, irq, evtchn, virq); if (ret < 0) { __unbind_from_irq(irq); irq = ret; goto out; } - bind_evtchn_to_cpu(evtchn, cpu); + bind_evtchn_to_cpu(xh, evtchn, cpu); } else { struct irq_info *info = info_for_irq(irq); WARN_ON(info == NULL || info->type != IRQT_VIRQ); @@ -1018,14 +1033,15 @@ static void unbind_from_irq(unsigned int irq) mutex_unlock(&irq_mapping_update_lock); } -int bind_evtchn_to_irqhandler(unsigned int evtchn, +int bind_evtchn_to_irqhandler(xenhost_t *xh, + unsigned int evtchn, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) { int irq, retval; - irq = bind_evtchn_to_irq(evtchn); + irq = bind_evtchn_to_irq(xh, evtchn); if (irq < 0) return irq; retval = request_irq(irq, handler, irqflags, devname, dev_id); @@ -1038,7 +1054,8 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn, } EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler); -int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, +int bind_interdomain_evtchn_to_irqhandler(xenhost_t *xh, + unsigned int remote_domain, unsigned int remote_port, irq_handler_t handler, unsigned long irqflags, @@ -1047,7 +1064,7 @@ int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, { int irq, retval; - irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port); + irq = bind_interdomain_evtchn_to_irq(xh, remote_domain, remote_port); if (irq < 0) return irq; @@ -1061,13 +1078,14 @@ int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, } EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irqhandler); -int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, +int bind_virq_to_irqhandler(xenhost_t *xh, + unsigned int virq, unsigned int cpu, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) { int irq, retval; - irq = bind_virq_to_irq(virq, cpu, irqflags & IRQF_PERCPU); + irq = bind_virq_to_irq(xh, virq, cpu, irqflags & IRQF_PERCPU); if (irq < 0) return irq; retval = request_irq(irq, handler, irqflags, devname, dev_id); @@ -1080,7 +1098,8 @@ int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, } EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler); -int bind_ipi_to_irqhandler(enum ipi_vector ipi, +int bind_ipi_to_irqhandler(xenhost_t *xh, + enum ipi_vector ipi, unsigned int cpu, irq_handler_t handler, unsigned long irqflags, @@ -1089,7 +1108,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, { int irq, retval; - irq = bind_ipi_to_irq(ipi, cpu); + irq = bind_ipi_to_irq(xh, ipi, cpu); if (irq < 0) return irq; @@ -1119,21 +1138,21 @@ EXPORT_SYMBOL_GPL(unbind_from_irqhandler); * @irq:irq bound to an event channel. * @priority: priority between XEN_IRQ_PRIORITY_MAX and XEN_IRQ_PRIORITY_MIN. */ -int xen_set_irq_priority(unsigned irq, unsigned priority) +int xen_set_irq_priority(xenhost_t *xh, unsigned irq, unsigned priority) { struct evtchn_set_priority set_priority; set_priority.port = evtchn_from_irq(irq); set_priority.priority = priority; - return HYPERVISOR_event_channel_op(EVTCHNOP_set_priority, + return hypervisor_event_channel_op(xh, EVTCHNOP_set_priority, &set_priority); } EXPORT_SYMBOL_GPL(xen_set_irq_priority); -int evtchn_make_refcounted(unsigned int evtchn) +int evtchn_make_refcounted(xenhost_t *xh, unsigned int evtchn) { - int irq = get_evtchn_to_irq(evtchn); + int irq = get_evtchn_to_irq(xh, evtchn); struct irq_info *info; if (irq == -1) @@ -1152,18 +1171,18 @@ int evtchn_make_refcounted(unsigned int evtchn) } EXPORT_SYMBOL_GPL(evtchn_make_refcounted); -int evtchn_get(unsigned int evtchn) +int evtchn_get(xenhost_t *xh, unsigned int evtchn) { int irq; struct irq_info *info; int err = -ENOENT; - if (evtchn >= xen_evtchn_max_channels()) + if (evtchn >= xen_evtchn_max_channels(xh)) return -EINVAL; mutex_lock(&irq_mapping_update_lock); - irq = get_evtchn_to_irq(evtchn); + irq = get_evtchn_to_irq(xh, evtchn); if (irq == -1) goto done; @@ -1185,22 +1204,22 @@ int evtchn_get(unsigned int evtchn) } EXPORT_SYMBOL_GPL(evtchn_get); -void evtchn_put(unsigned int evtchn) +void evtchn_put(xenhost_t *xh, unsigned int evtchn) { - int irq = get_evtchn_to_irq(evtchn); + int irq = get_evtchn_to_irq(xh, evtchn); if (WARN_ON(irq == -1)) return; unbind_from_irq(irq); } EXPORT_SYMBOL_GPL(evtchn_put); -void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector) +void xen_send_IPI_one(xenhost_t *xh, unsigned int cpu, enum ipi_vector vector) { int irq; #ifdef CONFIG_X86 if (unlikely(vector == XEN_NMI_VECTOR)) { - int rc = HYPERVISOR_vcpu_op(VCPUOP_send_nmi, xen_vcpu_nr(xh_default, cpu), + int rc = hypervisor_vcpu_op(xh, VCPUOP_send_nmi, xen_vcpu_nr(xh, cpu), NULL); if (rc < 0) printk(KERN_WARNING "Sending nmi to CPU%d failed (rc:%d)\n", cpu, rc); @@ -1216,23 +1235,26 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count); static void __xen_evtchn_do_upcall(void) { - struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); int cpu = get_cpu(); unsigned count; + xenhost_t **xh; - do { - vcpu_info->evtchn_upcall_pending = 0; + for_each_xenhost(xh) { + struct vcpu_info *vcpu_info = (*xh)->xen_vcpu[cpu]; + do { + vcpu_info->evtchn_upcall_pending = 0; - if (__this_cpu_inc_return(xed_nesting_count) - 1) - goto out; + if (__this_cpu_inc_return(xed_nesting_count) - 1) + goto out; - xen_evtchn_handle_events(cpu); + xen_evtchn_handle_events(*xh, cpu); - BUG_ON(!irqs_disabled()); + BUG_ON(!irqs_disabled()); - count = __this_cpu_read(xed_nesting_count); - __this_cpu_write(xed_nesting_count, 0); - } while (count != 1 || vcpu_info->evtchn_upcall_pending); + count = __this_cpu_read(xed_nesting_count); + __this_cpu_write(xed_nesting_count, 0); + } while (count != 1 || vcpu_info->evtchn_upcall_pending); + } out: @@ -1275,16 +1297,16 @@ void rebind_evtchn_irq(int evtchn, int irq) mutex_lock(&irq_mapping_update_lock); /* After resume the irq<->evtchn mappings are all cleared out */ - BUG_ON(get_evtchn_to_irq(evtchn) != -1); + BUG_ON(get_evtchn_to_irq(info->xh, evtchn) != -1); /* Expect irq to have been bound before, so there should be a proper type */ BUG_ON(info->type == IRQT_UNBOUND); - (void)xen_irq_info_evtchn_setup(irq, evtchn); + (void)xen_irq_info_evtchn_setup(info->xh, irq, evtchn); mutex_unlock(&irq_mapping_update_lock); - bind_evtchn_to_cpu(evtchn, info->cpu); + bind_evtchn_to_cpu(info->xh, evtchn, info->cpu); /* This will be deferred until interrupt is processed */ irq_set_affinity(irq, cpumask_of(info->cpu)); @@ -1293,7 +1315,7 @@ void rebind_evtchn_irq(int evtchn, int irq) } /* Rebind an evtchn so that it gets delivered to a specific cpu */ -int xen_rebind_evtchn_to_cpu(int evtchn, unsigned tcpu) +int xen_rebind_evtchn_to_cpu(xenhost_t *xh, int evtchn, unsigned tcpu) { struct evtchn_bind_vcpu bind_vcpu; int masked; @@ -1306,24 +1328,24 @@ int xen_rebind_evtchn_to_cpu(int evtchn, unsigned tcpu) /* Send future instances of this interrupt to other vcpu. */ bind_vcpu.port = evtchn; - bind_vcpu.vcpu = xen_vcpu_nr(xh_default, tcpu); + bind_vcpu.vcpu = xen_vcpu_nr(xh, tcpu); /* * Mask the event while changing the VCPU binding to prevent * it being delivered on an unexpected VCPU. */ - masked = test_and_set_mask(evtchn); + masked = test_and_set_mask(xh, evtchn); /* * 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(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0) - bind_evtchn_to_cpu(evtchn, tcpu); + if (hypervisor_event_channel_op(xh, EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0) + bind_evtchn_to_cpu(xh, evtchn, tcpu); if (!masked) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); return 0; } @@ -1333,7 +1355,10 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, bool force) { unsigned tcpu = cpumask_first_and(dest, cpu_online_mask); - int ret = xen_rebind_evtchn_to_cpu(evtchn_from_irq(data->irq), tcpu); + xenhost_t *xh = info_for_irq(data->irq)->xh; + int ret; + + ret = xen_rebind_evtchn_to_cpu(xh, evtchn_from_irq(data->irq), tcpu); if (!ret) irq_data_update_effective_affinity(data, cpumask_of(tcpu)); @@ -1344,38 +1369,41 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, static void enable_dynirq(struct irq_data *data) { int evtchn = evtchn_from_irq(data->irq); + xenhost_t *xh = info_for_irq(data->irq)->xh; if (VALID_EVTCHN(evtchn)) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); } static void disable_dynirq(struct irq_data *data) { int evtchn = evtchn_from_irq(data->irq); + xenhost_t *xh = info_for_irq(data->irq)->xh; if (VALID_EVTCHN(evtchn)) - mask_evtchn(evtchn); + mask_evtchn(xh, evtchn); } static void ack_dynirq(struct irq_data *data) { int evtchn = evtchn_from_irq(data->irq); + xenhost_t *xh = info_for_irq(data->irq)->xh; if (!VALID_EVTCHN(evtchn)) return; if (unlikely(irqd_is_setaffinity_pending(data)) && likely(!irqd_irq_disabled(data))) { - int masked = test_and_set_mask(evtchn); + int masked = test_and_set_mask(xh, evtchn); - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); irq_move_masked_irq(data); if (!masked) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); } else - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); } static void mask_ack_dynirq(struct irq_data *data) @@ -1387,15 +1415,16 @@ static void mask_ack_dynirq(struct irq_data *data) static int retrigger_dynirq(struct irq_data *data) { unsigned int evtchn = evtchn_from_irq(data->irq); + xenhost_t *xh = info_for_irq(data->irq)->xh; int masked; if (!VALID_EVTCHN(evtchn)) return 0; - masked = test_and_set_mask(evtchn); - set_evtchn(evtchn); + masked = test_and_set_mask(xh, evtchn); + set_evtchn(xh, evtchn); if (!masked) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); return 1; } @@ -1442,24 +1471,26 @@ static void restore_cpu_virqs(unsigned int cpu) { struct evtchn_bind_virq bind_virq; int virq, irq, evtchn; + xenhost_t *xh; for (virq = 0; virq < NR_VIRQS; virq++) { if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) continue; + xh = info_for_irq(irq)->xh; BUG_ON(virq_from_irq(irq) != virq); /* Get a new binding from Xen. */ bind_virq.virq = virq; bind_virq.vcpu = xen_vcpu_nr(xh_default, cpu); - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, + if (hypervisor_event_channel_op(xh, EVTCHNOP_bind_virq, &bind_virq) != 0) BUG(); evtchn = bind_virq.port; /* Record the new mapping. */ - (void)xen_irq_info_virq_setup(cpu, irq, evtchn, virq); - bind_evtchn_to_cpu(evtchn, cpu); + (void)xen_irq_info_virq_setup(xh, cpu, irq, evtchn, virq); + bind_evtchn_to_cpu(xh, evtchn, cpu); } } @@ -1467,23 +1498,25 @@ static void restore_cpu_ipis(unsigned int cpu) { struct evtchn_bind_ipi bind_ipi; int ipi, irq, evtchn; + xenhost_t *xh; for (ipi = 0; ipi < XEN_NR_IPIS; ipi++) { if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) continue; + xh = info_for_irq(irq)->xh; BUG_ON(ipi_from_irq(irq) != ipi); /* Get a new binding from Xen. */ - bind_ipi.vcpu = xen_vcpu_nr(xh_default, cpu); - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, + bind_ipi.vcpu = xen_vcpu_nr(xh, cpu); + if (hypervisor_event_channel_op(xh, EVTCHNOP_bind_ipi, &bind_ipi) != 0) BUG(); evtchn = bind_ipi.port; /* Record the new mapping. */ - (void)xen_irq_info_ipi_setup(cpu, irq, evtchn, ipi); - bind_evtchn_to_cpu(evtchn, cpu); + (void)xen_irq_info_ipi_setup(xh, cpu, irq, evtchn, ipi); + bind_evtchn_to_cpu(xh, evtchn, cpu); } } @@ -1491,26 +1524,29 @@ static void restore_cpu_ipis(unsigned int cpu) void xen_clear_irq_pending(int irq) { int evtchn = evtchn_from_irq(irq); + xenhost_t *xh = info_for_irq(irq)->xh; if (VALID_EVTCHN(evtchn)) - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); } EXPORT_SYMBOL(xen_clear_irq_pending); void xen_set_irq_pending(int irq) { int evtchn = evtchn_from_irq(irq); + xenhost_t *xh = info_for_irq(irq)->xh; if (VALID_EVTCHN(evtchn)) - set_evtchn(evtchn); + set_evtchn(xh, evtchn); } bool xen_test_irq_pending(int irq) { int evtchn = evtchn_from_irq(irq); + xenhost_t *xh = info_for_irq(irq)->xh; bool ret = false; if (VALID_EVTCHN(evtchn)) - ret = test_evtchn(evtchn); + ret = test_evtchn(xh, evtchn); return ret; } @@ -1520,10 +1556,13 @@ bool xen_test_irq_pending(int irq) void xen_poll_irq_timeout(int irq, u64 timeout) { evtchn_port_t evtchn = evtchn_from_irq(irq); + xenhost_t *xh = info_for_irq(irq)->xh; if (VALID_EVTCHN(evtchn)) { struct sched_poll poll; + BUG_ON(xh->type != xenhost_r1); + poll.nr_ports = 1; poll.timeout = timeout; set_xen_guest_handle(poll.ports, &evtchn); @@ -1665,26 +1704,30 @@ void xen_callback_vector(void) {} static bool fifo_events = true; module_param(fifo_events, bool, 0); -void __init xen_init_IRQ(void) +void xen_init_IRQ(xenhost_t *xh) { int ret = -EINVAL; unsigned int evtchn; - if (fifo_events) - ret = xen_evtchn_fifo_init(); if (ret < 0) - xen_evtchn_2l_init(); + xen_evtchn_2l_init(xh); - evtchn_to_irq = kcalloc(EVTCHN_ROW(xen_evtchn_max_channels()), - sizeof(*evtchn_to_irq), GFP_KERNEL); - BUG_ON(!evtchn_to_irq); + xh->evtchn_to_irq = kcalloc(EVTCHN_ROW(xh, xen_evtchn_max_channels(xh)), + sizeof(*(xh->evtchn_to_irq)), GFP_KERNEL); + BUG_ON(!xh->evtchn_to_irq); /* No event channels are 'live' right now. */ - for (evtchn = 0; evtchn < xen_evtchn_nr_channels(); evtchn++) - mask_evtchn(evtchn); + for (evtchn = 0; evtchn < xen_evtchn_nr_channels(xh); evtchn++) + mask_evtchn(xh, evtchn); pirq_needs_eoi = pirq_needs_eoi_flag; + /* + * Callback vectors, HW irqs are only for xenhost_r1 + */ + if (xh->type != xenhost_r1) + return; + #ifdef CONFIG_X86 if (xen_pv_domain()) { irq_ctx_init(smp_processor_id()); diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index eed766219dd0..38ce98f96fbb 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c @@ -324,7 +324,7 @@ static void consume_one_event(unsigned cpu, q->head[priority] = head; } -static void __evtchn_fifo_handle_events(unsigned cpu, bool drop) +static void __evtchn_fifo_handle_events(xenhost_t *xh, unsigned cpu, bool drop) { struct evtchn_fifo_control_block *control_block; unsigned long ready; diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h index 50c2050a1e32..9293c2593846 100644 --- a/drivers/xen/events/events_internal.h +++ b/drivers/xen/events/events_internal.h @@ -21,6 +21,7 @@ enum xen_irq_type { /* * Packed IRQ information: * type - enum xen_irq_type + * xh - xenhost_t * * event channel - irq->event channel mapping * cpu - cpu this event channel is bound to * index - type-specific information: @@ -32,6 +33,7 @@ enum xen_irq_type { */ struct irq_info { struct list_head list; + xenhost_t *xh; int refcnt; enum xen_irq_type type; /* type */ unsigned irq; @@ -56,35 +58,32 @@ struct irq_info { #define PIRQ_MSI_GROUP (1 << 2) struct evtchn_ops { - unsigned (*max_channels)(void); - unsigned (*nr_channels)(void); + unsigned (*max_channels)(xenhost_t *xh); + unsigned (*nr_channels)(xenhost_t *xh); int (*setup)(struct irq_info *info); void (*bind_to_cpu)(struct irq_info *info, unsigned cpu); - void (*clear_pending)(unsigned port); - void (*set_pending)(unsigned port); - bool (*is_pending)(unsigned port); - bool (*test_and_set_mask)(unsigned port); - void (*mask)(unsigned port); - void (*unmask)(unsigned port); + void (*clear_pending)(xenhost_t *xh, unsigned port); + void (*set_pending)(xenhost_t *xh, unsigned port); + bool (*is_pending)(xenhost_t *xh, unsigned port); + bool (*test_and_set_mask)(xenhost_t *xh, unsigned port); + void (*mask)(xenhost_t *xh, unsigned port); + void (*unmask)(xenhost_t *xh, unsigned port); - void (*handle_events)(unsigned cpu); - void (*resume)(void); + void (*handle_events)(xenhost_t *xh, unsigned cpu); + void (*resume)(xenhost_t *xh); }; -extern const struct evtchn_ops *evtchn_ops; - -extern int **evtchn_to_irq; -int get_evtchn_to_irq(unsigned int evtchn); +int get_evtchn_to_irq(xenhost_t *xh, unsigned int evtchn); struct irq_info *info_for_irq(unsigned irq); unsigned cpu_from_irq(unsigned irq); -unsigned cpu_from_evtchn(unsigned int evtchn); +unsigned cpu_from_evtchn(xenhost_t *xh, unsigned int evtchn); -static inline unsigned xen_evtchn_max_channels(void) +static inline unsigned xen_evtchn_max_channels(xenhost_t *xh) { - return evtchn_ops->max_channels(); + return xh->evtchn_ops->max_channels(xh); } /* @@ -93,59 +92,62 @@ static inline unsigned xen_evtchn_max_channels(void) */ static inline int xen_evtchn_port_setup(struct irq_info *info) { - if (evtchn_ops->setup) - return evtchn_ops->setup(info); + if (info->xh->evtchn_ops->setup) + return info->xh->evtchn_ops->setup(info); return 0; } static inline void xen_evtchn_port_bind_to_cpu(struct irq_info *info, unsigned cpu) { - evtchn_ops->bind_to_cpu(info, cpu); + info->xh->evtchn_ops->bind_to_cpu(info, cpu); } -static inline void clear_evtchn(unsigned port) +static inline void clear_evtchn(xenhost_t *xh, unsigned port) { - evtchn_ops->clear_pending(port); + xh->evtchn_ops->clear_pending(xh, port); } -static inline void set_evtchn(unsigned port) +static inline void set_evtchn(xenhost_t *xh, unsigned port) { - evtchn_ops->set_pending(port); + xh->evtchn_ops->set_pending(xh, port); } -static inline bool test_evtchn(unsigned port) +static inline bool test_evtchn(xenhost_t *xh, unsigned port) { - return evtchn_ops->is_pending(port); + return xh->evtchn_ops->is_pending(xh, port); } -static inline bool test_and_set_mask(unsigned port) +static inline bool test_and_set_mask(xenhost_t *xh, unsigned port) { - return evtchn_ops->test_and_set_mask(port); + return xh->evtchn_ops->test_and_set_mask(xh, port); } -static inline void mask_evtchn(unsigned port) +static inline void mask_evtchn(xenhost_t *xh, unsigned port) { - return evtchn_ops->mask(port); + return xh->evtchn_ops->mask(xh, port); } -static inline void unmask_evtchn(unsigned port) +static inline void unmask_evtchn(xenhost_t *xh, unsigned port) { - return evtchn_ops->unmask(port); + return xh->evtchn_ops->unmask(xh, port); } -static inline void xen_evtchn_handle_events(unsigned cpu) +static inline void xen_evtchn_handle_events(xenhost_t *xh, unsigned cpu) { - return evtchn_ops->handle_events(cpu); + return xh->evtchn_ops->handle_events(xh, cpu); } static inline void xen_evtchn_resume(void) { - if (evtchn_ops->resume) - evtchn_ops->resume(); + xenhost_t **xh; + + for_each_xenhost(xh) + if ((*xh)->evtchn_ops->resume) + (*xh)->evtchn_ops->resume(*xh); } -void xen_evtchn_2l_init(void); -int xen_evtchn_fifo_init(void); +void xen_evtchn_2l_init(xenhost_t *xh); +int xen_evtchn_fifo_init(xenhost_t *xh); #endif /* #ifndef __EVENTS_INTERNAL_H__ */ diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c index 66622109f2be..b868816874fd 100644 --- a/drivers/xen/evtchn.c +++ b/drivers/xen/evtchn.c @@ -292,7 +292,7 @@ static ssize_t evtchn_write(struct file *file, const char __user *buf, evtchn = find_evtchn(u, port); if (evtchn && !evtchn->enabled) { evtchn->enabled = true; - enable_irq(irq_from_evtchn(port)); + enable_irq(irq_from_evtchn(xh_default, port)); } } @@ -392,18 +392,18 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port) if (rc < 0) goto err; - rc = bind_evtchn_to_irqhandler(port, evtchn_interrupt, 0, + rc = bind_evtchn_to_irqhandler(xh_default, port, evtchn_interrupt, 0, u->name, evtchn); if (rc < 0) goto err; - rc = evtchn_make_refcounted(port); + rc = evtchn_make_refcounted(xh_default, port); return rc; err: /* bind failed, should close the port now */ close.port = port; - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) + if (hypervisor_event_channel_op(xh_default, EVTCHNOP_close, &close) != 0) BUG(); del_evtchn(u, evtchn); return rc; @@ -412,7 +412,7 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port) static void evtchn_unbind_from_user(struct per_user_data *u, struct user_evtchn *evtchn) { - int irq = irq_from_evtchn(evtchn->port); + int irq = irq_from_evtchn(xh_default, evtchn->port); BUG_ON(irq < 0); @@ -429,7 +429,7 @@ static void evtchn_bind_interdom_next_vcpu(int evtchn) struct irq_desc *desc; unsigned long flags; - irq = irq_from_evtchn(evtchn); + irq = irq_from_evtchn(xh_default, evtchn); desc = irq_to_desc(irq); if (!desc) @@ -447,7 +447,7 @@ static void evtchn_bind_interdom_next_vcpu(int evtchn) this_cpu_write(bind_last_selected_cpu, selected_cpu); /* unmask expects irqs to be disabled */ - xen_rebind_evtchn_to_cpu(evtchn, selected_cpu); + xen_rebind_evtchn_to_cpu(xh_default, evtchn, selected_cpu); raw_spin_unlock_irqrestore(&desc->lock, flags); } @@ -549,7 +549,7 @@ static long evtchn_ioctl(struct file *file, break; rc = -EINVAL; - if (unbind.port >= xen_evtchn_nr_channels()) + if (unbind.port >= xen_evtchn_nr_channels(xh_default)) break; rc = -ENOTCONN; @@ -557,7 +557,7 @@ static long evtchn_ioctl(struct file *file, if (!evtchn) break; - disable_irq(irq_from_evtchn(unbind.port)); + disable_irq(irq_from_evtchn(xh_default, unbind.port)); evtchn_unbind_from_user(u, evtchn); rc = 0; break; @@ -574,7 +574,7 @@ static long evtchn_ioctl(struct file *file, rc = -ENOTCONN; evtchn = find_evtchn(u, notify.port); if (evtchn) { - notify_remote_via_evtchn(notify.port); + notify_remote_via_evtchn(xh_default, notify.port); rc = 0; } break; @@ -676,7 +676,7 @@ static int evtchn_release(struct inode *inode, struct file *filp) struct user_evtchn *evtchn; evtchn = rb_entry(node, struct user_evtchn, node); - disable_irq(irq_from_evtchn(evtchn->port)); + disable_irq(irq_from_evtchn(xh_default, evtchn->port)); evtchn_unbind_from_user(u, evtchn); } diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c index ae81cf75ae5f..9f54fb8cf96d 100644 --- a/drivers/xen/fallback.c +++ b/drivers/xen/fallback.c @@ -2,6 +2,7 @@ #include <linux/string.h> #include <linux/bug.h> #include <linux/export.h> +#include <xen/interface/xen.h> #include <asm/hypervisor.h> #include <asm/xen/hypercall.h> diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c index 3fa40c723e8e..e07823886fa8 100644 --- a/drivers/xen/gntalloc.c +++ b/drivers/xen/gntalloc.c @@ -189,8 +189,8 @@ static void __del_gref(struct gntalloc_gref *gref) kunmap(gref->page); } if (gref->notify.flags & UNMAP_NOTIFY_SEND_EVENT) { - notify_remote_via_evtchn(gref->notify.event); - evtchn_put(gref->notify.event); + notify_remote_via_evtchn(xh_default, gref->notify.event); + evtchn_put(xh_default, gref->notify.event); } gref->notify.flags = 0; @@ -418,14 +418,14 @@ static long gntalloc_ioctl_unmap_notify(struct gntalloc_file_private_data *priv, * reference to that event channel. */ if (op.action & UNMAP_NOTIFY_SEND_EVENT) { - if (evtchn_get(op.event_channel_port)) { + if (evtchn_get(xh_default, op.event_channel_port)) { rc = -EINVAL; goto unlock_out; } } if (gref->notify.flags & UNMAP_NOTIFY_SEND_EVENT) - evtchn_put(gref->notify.event); + evtchn_put(xh_default, gref->notify.event); gref->notify.flags = op.action; gref->notify.pgoff = pgoff; diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 5efc5eee9544..0f0c951cd5b1 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -247,8 +247,8 @@ void gntdev_put_map(struct gntdev_priv *priv, struct gntdev_grant_map *map) atomic_sub(map->count, &pages_mapped); if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT) { - notify_remote_via_evtchn(map->notify.event); - evtchn_put(map->notify.event); + notify_remote_via_evtchn(xh_default, map->notify.event); + evtchn_put(xh_default, map->notify.event); } if (populate_freeable_maps && priv) { @@ -790,7 +790,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) * reference to that event channel. */ if (op.action & UNMAP_NOTIFY_SEND_EVENT) { - if (evtchn_get(op.event_channel_port)) + if (evtchn_get(xh_default, op.event_channel_port)) return -EINVAL; } @@ -829,7 +829,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) /* Drop the reference to the event channel we did not save in the map */ if (out_flags & UNMAP_NOTIFY_SEND_EVENT) - evtchn_put(out_event); + evtchn_put(xh_default, out_event); return rc; } diff --git a/drivers/xen/mcelog.c b/drivers/xen/mcelog.c index b8bf61abb65b..45be85960f53 100644 --- a/drivers/xen/mcelog.c +++ b/drivers/xen/mcelog.c @@ -378,7 +378,7 @@ static int bind_virq_for_mce(void) return ret; } - ret = bind_virq_to_irqhandler(VIRQ_MCA, 0, + ret = bind_virq_to_irqhandler(xh_default, VIRQ_MCA, 0, xen_mce_interrupt, 0, "mce", NULL); if (ret < 0) { pr_err("Failed to bind virq\n"); diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c index cdc6daa7a9f6..d0807f8fbd8b 100644 --- a/drivers/xen/pcpu.c +++ b/drivers/xen/pcpu.c @@ -387,7 +387,7 @@ static int __init xen_pcpu_init(void) if (!xen_initial_domain()) return -ENODEV; - irq = bind_virq_to_irqhandler(VIRQ_PCPU_STATE, 0, + irq = bind_virq_to_irqhandler(xh_default, VIRQ_PCPU_STATE, 0, xen_pcpu_interrupt, 0, "xen-pcpu", NULL); if (irq < 0) { diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c index 08cb419eb4e6..b5f16a98414b 100644 --- a/drivers/xen/preempt.c +++ b/drivers/xen/preempt.c @@ -10,6 +10,7 @@ */ #include <linux/sched.h> +#include <xen/interface/xen.h> #include <xen/xen-ops.h> #ifndef CONFIG_PREEMPT diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index b24ddac1604b..b5541f862720 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -27,6 +27,7 @@ #include <asm/pgalloc.h> #include <asm/pgtable.h> #include <asm/tlb.h> +#include <xen/interface/xen.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index 9d314bba7c4e..005a898e7a23 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c @@ -13,12 +13,12 @@ #include <linux/kobject.h> #include <linux/err.h> +#include <xen/interface/xen.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> #include <xen/xen.h> #include <xen/xenbus.h> -#include <xen/interface/xen.h> #include <xen/interface/version.h> #ifdef CONFIG_XEN_HAVE_VPMU #include <xen/interface/xenpmu.h> diff --git a/drivers/xen/time.c b/drivers/xen/time.c index feee74bbab0a..73916766dcac 100644 --- a/drivers/xen/time.c +++ b/drivers/xen/time.c @@ -8,13 +8,13 @@ #include <linux/gfp.h> #include <linux/slab.h> +#include <xen/interface/xen.h> #include <asm/paravirt.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> #include <xen/events.h> #include <xen/features.h> -#include <xen/interface/xen.h> #include <xen/interface/vcpu.h> #include <xen/xen-ops.h> diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c index 581c4e1a8b82..b95dd65f3872 100644 --- a/drivers/xen/xen-pciback/xenbus.c +++ b/drivers/xen/xen-pciback/xenbus.c @@ -123,7 +123,7 @@ static int xen_pcibk_do_attach(struct xen_pcibk_device *pdev, int gnt_ref, pdev->sh_info = vaddr; - err = bind_interdomain_evtchn_to_irqhandler( + err = bind_interdomain_evtchn_to_irqhandler(xh_default, pdev->xdev->otherend_id, remote_evtchn, xen_pcibk_handle_event, 0, DRV_NAME, pdev); if (err < 0) { diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index c9e23a126218..8702b1ac92a8 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -54,8 +54,9 @@ #include <target/target_core_base.h> #include <target/target_core_fabric.h> + +#include <xen/interface/xen.h> #include <asm/hypervisor.h> - #include <xen/xen.h> #include <xen/balloon.h> #include <xen/events.h> @@ -829,7 +830,7 @@ static int scsiback_init_sring(struct vscsibk_info *info, grant_ref_t ring_ref, sring = (struct vscsiif_sring *)area; BACK_RING_INIT(&info->ring, sring, PAGE_SIZE); - err = bind_interdomain_evtchn_to_irq(info->domid, evtchn); + err = bind_interdomain_evtchn_to_irq(xh_default, info->domid, evtchn); if (err < 0) goto unmap_page; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index e17ca8156171..f0cf47765726 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -36,9 +36,9 @@ #include <linux/spinlock.h> #include <linux/vmalloc.h> #include <linux/export.h> -#include <asm/xen/hypervisor.h> #include <xen/page.h> #include <xen/interface/xen.h> +#include <asm/xen/hypervisor.h> #include <xen/interface/event_channel.h> #include <xen/balloon.h> #include <xen/events.h> diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index d239fc3c5e3d..acbc366c1717 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c @@ -151,7 +151,7 @@ static int xb_write(const void *data, unsigned int len) /* Implies mb(): other side will see the updated producer. */ if (prod <= intf->req_cons) - notify_remote_via_evtchn(xen_store_evtchn); + notify_remote_via_evtchn(xh_default, xen_store_evtchn); } return bytes; @@ -204,7 +204,7 @@ static int xb_read(void *data, unsigned int len) /* Implies mb(): other side will see the updated consumer. */ if (intf->rsp_prod - cons >= XENSTORE_RING_SIZE) - notify_remote_via_evtchn(xen_store_evtchn); + notify_remote_via_evtchn(xh_default, xen_store_evtchn); } return bytes; @@ -461,7 +461,7 @@ int xb_init_comms(void) } else { int err; - err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting, + err = bind_evtchn_to_irqhandler(xh_default, xen_store_evtchn, wake_waiting, 0, "xenbus", &xb_waitq); if (err < 0) { pr_err("request irq failed %i\n", err); diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 5b471889d723..049bd511f36e 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -52,6 +52,7 @@ #include <asm/page.h> #include <asm/pgtable.h> +#include <xen/interface/xen.h> #include <asm/xen/hypervisor.h> #include <xen/xen.h> diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index b0bed4faf44c..d3c53a9db5e3 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -48,6 +48,7 @@ #include <asm/page.h> #include <asm/pgtable.h> +#include <xen/interface/xen.h> #include <asm/xen/hypervisor.h> #include <asm/hypervisor.h> #include <xen/xenbus.h> diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 07896f4b2736..3edab7cc03c3 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -19,6 +19,7 @@ #include <asm/page.h> #include <asm/pgtable.h> +#include <xen/interface/xen.h> #include <asm/xen/hypervisor.h> #include <xen/xenbus.h> #include <xen/events.h> diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 3236d1b1fa01..74c2b9416b88 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -46,6 +46,7 @@ #include <linux/reboot.h> #include <linux/rwsem.h> #include <linux/mutex.h> +#include <xen/interface/xen.h> #include <asm/xen/hypervisor.h> #include <xen/xenbus.h> #include <xen/xen.h> diff --git a/include/xen/events.h b/include/xen/events.h index a48897199975..138dbbbefc6d 100644 --- a/include/xen/events.h +++ b/include/xen/events.h @@ -11,27 +11,30 @@ #include <asm/xen/hypercall.h> #include <asm/xen/events.h> -unsigned xen_evtchn_nr_channels(void); +unsigned xen_evtchn_nr_channels(xenhost_t *xh); -int bind_evtchn_to_irq(unsigned int evtchn); -int bind_evtchn_to_irqhandler(unsigned int evtchn, +int bind_evtchn_to_irq(xenhost_t *xh, unsigned int evtchn); +int bind_evtchn_to_irqhandler(xenhost_t *xh, unsigned int evtchn, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id); -int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu); -int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, +int bind_virq_to_irq(xenhost_t *xh, unsigned int virq, unsigned int cpu, bool percpu); +int bind_virq_to_irqhandler(xenhost_t *xh, unsigned int virq, unsigned int cpu, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id); -int bind_ipi_to_irqhandler(enum ipi_vector ipi, +int bind_ipi_to_irqhandler(xenhost_t *xh, + enum ipi_vector ipi, unsigned int cpu, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id); -int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, +int bind_interdomain_evtchn_to_irq(xenhost_t *xh, + unsigned int remote_domain, unsigned int remote_port); -int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, +int bind_interdomain_evtchn_to_irqhandler(xenhost_t *xh, + unsigned int remote_domain, unsigned int remote_port, irq_handler_t handler, unsigned long irqflags, @@ -48,23 +51,23 @@ void unbind_from_irqhandler(unsigned int irq, void *dev_id); #define XEN_IRQ_PRIORITY_MAX EVTCHN_FIFO_PRIORITY_MAX #define XEN_IRQ_PRIORITY_DEFAULT EVTCHN_FIFO_PRIORITY_DEFAULT #define XEN_IRQ_PRIORITY_MIN EVTCHN_FIFO_PRIORITY_MIN -int xen_set_irq_priority(unsigned irq, unsigned priority); +int xen_set_irq_priority(xenhost_t *xh, unsigned irq, unsigned priority); /* * Allow extra references to event channels exposed to userspace by evtchn */ -int evtchn_make_refcounted(unsigned int evtchn); -int evtchn_get(unsigned int evtchn); -void evtchn_put(unsigned int evtchn); +int evtchn_make_refcounted(xenhost_t *xh, unsigned int evtchn); +int evtchn_get(xenhost_t *xh, unsigned int evtchn); +void evtchn_put(xenhost_t *xh, unsigned int evtchn); -void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector); +void xen_send_IPI_one(xenhost_t *xh, unsigned int cpu, enum ipi_vector vector); void rebind_evtchn_irq(int evtchn, int irq); -int xen_rebind_evtchn_to_cpu(int evtchn, unsigned tcpu); +int xen_rebind_evtchn_to_cpu(xenhost_t *xh, int evtchn, unsigned tcpu); -static inline void notify_remote_via_evtchn(int port) +static inline void notify_remote_via_evtchn(xenhost_t *xh, int port) { struct evtchn_send send = { .port = port }; - (void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); + (void)hypervisor_event_channel_op(xh, EVTCHNOP_send, &send); } void notify_remote_via_irq(int irq); @@ -85,7 +88,7 @@ void xen_poll_irq(int irq); void xen_poll_irq_timeout(int irq, u64 timeout); /* Determine the IRQ which is bound to an event channel */ -unsigned irq_from_evtchn(unsigned int evtchn); +unsigned irq_from_evtchn(xenhost_t *xh,unsigned int evtchn); int irq_from_virq(unsigned int cpu, unsigned int virq); unsigned int evtchn_from_irq(unsigned irq); @@ -101,14 +104,14 @@ void xen_evtchn_do_upcall(struct pt_regs *regs); void xen_hvm_evtchn_do_upcall(void); /* Bind a pirq for a physical interrupt to an irq. */ -int xen_bind_pirq_gsi_to_irq(unsigned gsi, +int xen_bind_pirq_gsi_to_irq(xenhost_t *xh, unsigned gsi, unsigned pirq, int shareable, char *name); #ifdef CONFIG_PCI_MSI /* Allocate a pirq for a MSI style physical interrupt. */ -int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); +int xen_allocate_pirq_msi(xenhost_t *xh, struct pci_dev *dev, struct msi_desc *msidesc); /* Bind an PSI pirq to an irq. */ -int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, +int xen_bind_pirq_msi_to_irq(xenhost_t *xh, struct pci_dev *dev, struct msi_desc *msidesc, int pirq, int nvec, const char *name, domid_t domid); #endif @@ -128,5 +131,5 @@ int xen_irq_from_gsi(unsigned gsi); int xen_test_irq_shared(int irq); /* initialize Xen IRQ subsystem */ -void xen_init_IRQ(void); +void xen_init_IRQ(xenhost_t *xh); #endif /* _XEN_EVENTS_H */ diff --git a/include/xen/xenhost.h b/include/xen/xenhost.h index f6092a8987f1..c9dabf739ff8 100644 --- a/include/xen/xenhost.h +++ b/include/xen/xenhost.h @@ -112,6 +112,23 @@ typedef struct { */ uint32_t xen_vcpu_id[NR_CPUS]; }; + + /* + * evtchn: get init'd via x86_init.irqs.intr_init (xen_init_IRQ()). + * + * The common functionality for xenhost_* provided by xen_init_IRQ() + * is the mapping between evtchn <-> irq. + * + * For all three of xenhost_r0/r1 and r2, post-init the evtchn logic + * should just work using the evtchn_to_irq mapping and the vcpu_info, + * shared_info state. + * (Plus some state private to evtchn_2l/evtchn_fifo which for now + * is defined locally.) + */ + struct { + const struct evtchn_ops *evtchn_ops; + int **evtchn_to_irq; + }; } xenhost_t; typedef struct xenhost_ops { -- 2.20.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |