From nobody Wed Apr 24 11:22:44 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=oracle.com ARC-Seal: i=1; a=rsa-sha256; t=1557422837; cv=none; d=zoho.com; s=zohoarc; b=c7AeAYkL1zl8HZ48cHKaEdhnFAjcf4VmVVVOMkGolu5Sx2Cx0VwlrkeQOPdLHnO5LuSe3b9V945pD2TNa3foB54SqL6i1jrodhH4gB6EeXtuLkhpZMqR/P3LwTejj41IOG1QUiuUrcpOjflN0FObF7JOnfA0361VlGDZoptRd44= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1557422837; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=WH9+GUDU2mvkeLcr8ZXuLEawaZVscSrAdC7tW70Y29o=; b=fNc94VmmzLVtyiKdZSwGjM5aDulMHEZ6/T4WAJsu7XaTFx/zG9H86dya4CYDHKvxjs8kdcX9kh9Lrv+1xYm9ey0TGSvlLm5ogQXH5ejYHZkasf4gMIEpvhEXQBHGuDMtpiL8TRVZUGbe6sKM/GBoEBcJNsWjGM88KKMJOGREWEY= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1557422837645815.8218455551385; Thu, 9 May 2019 10:27:17 -0700 (PDT) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hOmnq-0000nq-Ol; Thu, 09 May 2019 17:25:54 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hOmno-0000jW-B2 for xen-devel@lists.xenproject.org; Thu, 09 May 2019 17:25:52 +0000 Received: from userp2120.oracle.com (unknown [156.151.31.85]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 7a71b258-727f-11e9-8980-bc764e045a96; Thu, 09 May 2019 17:25:45 +0000 (UTC) Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x49HJSjx169527; Thu, 9 May 2019 17:25:44 GMT Received: from userp3030.oracle.com (userp3030.oracle.com [156.151.31.80]) by userp2120.oracle.com with ESMTP id 2s94b14e37-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 09 May 2019 17:25:43 +0000 Received: from pps.filterd (userp3030.oracle.com [127.0.0.1]) by userp3030.oracle.com (8.16.0.27/8.16.0.27) with SMTP id x49HNxXW109619; Thu, 9 May 2019 17:25:43 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userp3030.oracle.com with ESMTP id 2sagyvcg5g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 09 May 2019 17:25:43 +0000 Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id x49HPgv9013341; Thu, 9 May 2019 17:25:42 GMT Received: from aa1-ca-oracle-com.ca.oracle.com (/10.156.75.204) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 09 May 2019 10:25:42 -0700 X-Inumbo-ID: 7a71b258-727f-11e9-8980-bc764e045a96 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=corp-2018-07-02; bh=MX9dv0NPMRnpuOl3rTjmwHelV02ePW2ATwYcVL+LHbQ=; b=Sb0IrlLE3JgnmhnTHhBFroebbxxZ25AboDrUPvKSYzIkmhsokEx522XlFxDQqi2yKZeJ ld4UdiVo+2PLp+oOImwR9x8GjQzMRRk9iYaaGNlF5BBrhDks1U10NFMWMwPE6MkB+Ed1 OL6dqVGhfRFH2QkgMn70IQEO1ln0owsVx6pVmuxger5NVudJylPdn1iwDAzn+3MYFRwz ft1gpNVARaOb7/RLXN8T+ye2jUFBOHnnha/bFkqsmGSqGiWwHyYnlTY1gDbRIZkWLUXM G5Movzi7EUXWLpRxh5n49bjhJVnxf6DaRMRJluLYrD7nezC/vYbV85LOK3MkzcrNRKBQ Ag== From: Ankur Arora To: linux-kernel@vger.kernel.org, xen-devel@lists.xenproject.org Date: Thu, 9 May 2019 10:25:33 -0700 Message-Id: <20190509172540.12398-10-ankur.a.arora@oracle.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190509172540.12398-1-ankur.a.arora@oracle.com> References: <20190509172540.12398-1-ankur.a.arora@oracle.com> MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=9252 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=2 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1905090100 X-Proofpoint-Virus-Version: vendor=nai engine=5900 definitions=9252 signatures=668686 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=2 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1905090100 Subject: [Xen-devel] [RFC PATCH 09/16] xen/evtchn: support evtchn in xenhost_t X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: jgross@suse.com, sstabellini@kernel.org, konrad.wilk@oracle.com, ankur.a.arora@oracle.com, pbonzini@redhat.com, boris.ostrovsky@oracle.com, joao.m.martins@oracle.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) 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 --- 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 =20 #include +#include +#include =20 #include #include @@ -46,7 +48,7 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev) if (gsi < nr_legacy_irqs()) share =3D 0; =20 - rc =3D xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront"); + rc =3D 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, i= nt triggering, if (gsi_override >=3D 0) gsi =3D gsi_override; =20 - irq =3D xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name); + irq =3D xen_bind_pirq_gsi_to_irq(xh_default, gsi, map_irq.pirq, shareable= , name); if (irq < 0) goto out; =20 @@ -180,7 +182,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int = nvec, int type) goto error; i =3D 0; for_each_pci_msi_entry(msidesc, dev) { - irq =3D xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], + irq =3D xen_bind_pirq_msi_to_irq(xh_default, dev, msidesc, v[i], (type =3D=3D PCI_CAP_ID_MSI) ? nvec : 1, (type =3D=3D 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; =20 for_each_pci_msi_entry(msidesc, dev) { - pirq =3D xen_allocate_pirq_msi(dev, msidesc); + pirq =3D xen_allocate_pirq_msi(xh_default, dev, msidesc); if (pirq < 0) { irq =3D -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=3D%d\n", pirq); - irq =3D xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, + irq =3D xen_bind_pirq_msi_to_irq(xh_default, dev, msidesc, pirq, (type =3D=3D PCI_CAP_ID_MSI) ? nvec : 1, (type =3D=3D PCI_CAP_ID_MSIX) ? "msi-x" : "msi", @@ -337,7 +339,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *d= ev, int nvec, int type) goto out; } =20 - ret =3D xen_bind_pirq_msi_to_irq(dev, msidesc, map_irq.pirq, + ret =3D xen_bind_pirq_msi_to_irq(xh_default, dev, msidesc, map_irq.pirq, (type =3D=3D PCI_CAP_ID_MSI) ? nvec : 1, (type =3D=3D PCI_CAP_ID_MSIX) ? "msi-x" := "msi", domid); @@ -496,7 +498,7 @@ int __init pci_xen_initial_domain(void) } if (0 =3D=3D nr_ioapics) { for (irq =3D 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 =3D xen_init_IRQ; + x86_init.irqs.intr_init =3D xenhost_init_IRQ; xen_hvm_init_time_ops(); xen_hvm_init_mmu_ops(); =20 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 = =3D { void __init xen_init_irq_ops(void) { pv_ops.irq =3D xen_irq_ops; - x86_init.irqs.intr_init =3D xen_init_IRQ; + x86_init.irqs.intr_init =3D 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; =20 resched_name =3D kasprintf(GFP_KERNEL, "resched%d", cpu); - rc =3D bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, + rc =3D 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 =3D resched_name; =20 callfunc_name =3D kasprintf(GFP_KERNEL, "callfunc%d", cpu); - rc =3D bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, + rc =3D 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 =3D callfunc_name; =20 debug_name =3D kasprintf(GFP_KERNEL, "debug%d", cpu); - rc =3D bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt, + rc =3D bind_virq_to_irqhandler(xh_default, VIRQ_DEBUG, cpu, xen_debug_int= errupt, 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 =3D debug_name; =20 callfunc_name =3D kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu); - rc =3D bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR, + rc =3D 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) =20 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); } =20 static void __xen_send_IPI_mask(const struct cpumask *mask, @@ -164,7 +164,7 @@ static void __xen_send_IPI_mask(const struct cpumask *m= ask, unsigned cpu; =20 for_each_cpu_and(cpu, mask, cpu_online_mask) - xen_send_IPI_one(cpu, vector); + xen_send_IPI_one(xh_default, cpu, vector); } =20 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 =3D xen_map_vector(vector); =20 if (xen_vector >=3D 0) - xen_send_IPI_one(smp_processor_id(), xen_vector); + xen_send_IPI_one(xh_default, smp_processor_id(), xen_vector); } =20 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 =3D=3D cpu) continue; =20 - xen_send_IPI_one(cpu, xen_vector); + xen_send_IPI_one(xh_default, cpu, xen_vector); } } =20 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; =20 callfunc_name =3D kasprintf(GFP_KERNEL, "irqwork%d", cpu); - rc =3D bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR, + rc =3D 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) =20 if (is_xen_pmu(cpu)) { pmu_name =3D kasprintf(GFP_KERNEL, "pmu%d", cpu); - rc =3D bind_virq_to_irqhandler(VIRQ_XENPMU, cpu, + rc =3D 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) =20 snprintf(xevt->name, sizeof(xevt->name), "timer%d", cpu); =20 - irq =3D bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, + irq =3D 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); =20 memcpy(evt, xen_clockevent, sizeof(*evt)); =20 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); =20 #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 #include #include +#include #include "xen-ops.h" =20 /* @@ -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, g= rant_ref_t *gref, BUG(); } =20 - err =3D bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn, + err =3D bind_interdomain_evtchn_to_irqhandler(xh_default, blkif->domid, e= vtchn, 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; =20 - err =3D bind_evtchn_to_irqhandler(rinfo->evtchn, blkif_interrupt, 0, + err =3D bind_evtchn_to_irqhandler(xh_default, rinfo->evtchn, blkif_interr= upt, 0, "blkif", rinfo); if (err <=3D 0) { xenbus_dev_fatal(dev, err, diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbd= front.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 =3D xenbus_alloc_evtchn(dev, &evtchn); if (ret) goto error_grant; - ret =3D bind_evtchn_to_irqhandler(evtchn, input_handler, + ret =3D 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 =3D (struct xen_netif_ctrl_sring *)addr; BACK_RING_INIT(&vif->ctrl, shared, XEN_PAGE_SIZE); =20 - err =3D bind_interdomain_evtchn_to_irq(vif->domid, evtchn); + err =3D bind_interdomain_evtchn_to_irq(xh_default, vif->domid, evtchn); if (err < 0) goto err_unmap; =20 @@ -646,7 +646,7 @@ int xenvif_connect_data(struct xenvif_queue *queue, =20 if (tx_evtchn =3D=3D rx_evtchn) { /* feature-split-event-channels =3D=3D 0 */ - err =3D bind_interdomain_evtchn_to_irqhandler( + err =3D 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 =3D=3D 1 */ snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name), "%s-tx", queue->name); - err =3D bind_interdomain_evtchn_to_irqhandler( + err =3D 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, =20 snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name), "%s-rx", queue->name); - err =3D bind_interdomain_evtchn_to_irqhandler( + err =3D 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_queu= e *queue) if (err < 0) goto fail; =20 - err =3D bind_evtchn_to_irqhandler(queue->tx_evtchn, + err =3D 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) =20 snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name), "%s-tx", queue->name); - err =3D bind_evtchn_to_irqhandler(queue->tx_evtchn, + err =3D 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) =20 snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name), "%s-rx", queue->name); - err =3D bind_evtchn_to_irqhandler(queue->rx_evtchn, + err =3D 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; =20 - err =3D bind_evtchn_to_irqhandler(pdev->evtchn, pcifront_handler_aer, + err =3D bind_evtchn_to_irqhandler(xh_default, pdev->evtchn, pcifront_hand= ler_aer, 0, "pcifront", pdev); =20 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. */ =20 +#include +#include #include #include #include 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 #include =20 +#include #include #include =20 #include -#include #include #include #include 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 +=3D events.o =20 events-y +=3D events_base.o events-y +=3D events_2l.o -events-y +=3D 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 @@ =20 #define EVTCHN_MASK_SIZE (EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD) =20 -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); =20 -static unsigned evtchn_2l_max_channels(void) +static unsigned evtchn_2l_max_channels(xenhost_t *xh) { return EVTCHN_2L_NR_CHANNELS; } =20 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]); } =20 -static void evtchn_2l_clear_pending(unsigned port) +static void evtchn_2l_clear_pending(xenhost_t *xh, unsigned port) { struct shared_info *s =3D xh_default->HYPERVISOR_shared_info; sync_clear_bit(port, BM(&s->evtchn_pending[0])); } =20 -static void evtchn_2l_set_pending(unsigned port) +static void evtchn_2l_set_pending(xenhost_t *xh, unsigned port) { struct shared_info *s =3D xh_default->HYPERVISOR_shared_info; sync_set_bit(port, BM(&s->evtchn_pending[0])); } =20 -static bool evtchn_2l_is_pending(unsigned port) +static bool evtchn_2l_is_pending(xenhost_t *xh, unsigned port) { - struct shared_info *s =3D xh_default->HYPERVISOR_shared_info; + struct shared_info *s =3D xh->HYPERVISOR_shared_info; return sync_test_bit(port, BM(&s->evtchn_pending[0])); } =20 -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 =3D xh_default->HYPERVISOR_shared_info; + struct shared_info *s =3D xh->HYPERVISOR_shared_info; return sync_test_and_set_bit(port, BM(&s->evtchn_mask[0])); } =20 -static void evtchn_2l_mask(unsigned port) +static void evtchn_2l_mask(xenhost_t *xh, unsigned port) { struct shared_info *s =3D xh_default->HYPERVISOR_shared_info; sync_set_bit(port, BM(&s->evtchn_mask[0])); } =20 -static void evtchn_2l_unmask(unsigned port) +static void evtchn_2l_unmask(xenhost_t *xh, unsigned port) { struct shared_info *s =3D xh_default->HYPERVISOR_shared_info; unsigned int cpu =3D get_cpu(); @@ -91,7 +93,7 @@ static void evtchn_2l_unmask(unsigned port) =20 BUG_ON(!irqs_disabled()); =20 - if (unlikely((cpu !=3D cpu_from_evtchn(port)))) + if (unlikely((cpu !=3D cpu_from_evtchn(xh, port)))) do_hypercall =3D 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 =3D { .port =3D port }; - (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); + (void)hypervisor_event_channel_op(xh, EVTCHNOP_unmask, &unmask); } else { - struct vcpu_info *vcpu_info =3D __this_cpu_read(xen_vcpu); + struct vcpu_info *vcpu_info =3D xh->xen_vcpu[cpu]; =20 /* * The following is basically the equivalent of @@ -134,8 +136,8 @@ static void evtchn_2l_unmask(unsigned port) put_cpu(); } =20 -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); =20 /* * 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)) =20 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]; } =20 @@ -159,7 +162,7 @@ static inline xen_ulong_t active_evtchns(unsigned int c= pu, * 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 =3D xh_default->HYPERVISOR_shared_info; - struct vcpu_info *vcpu_info =3D __this_cpu_read(xen_vcpu); + struct shared_info *s =3D xh->HYPERVISOR_shared_info; + struct vcpu_info *vcpu_info =3D xh->xen_vcpu[cpu]; =20 /* Timer interrupt has highest priority. */ irq =3D irq_from_virq(cpu, VIRQ_TIMER); @@ -176,7 +179,7 @@ static void evtchn_2l_handle_events(unsigned cpu) unsigned int evtchn =3D evtchn_from_irq(irq); word_idx =3D evtchn / BITS_PER_LONG; bit_idx =3D 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); } =20 @@ -187,8 +190,8 @@ static void evtchn_2l_handle_events(unsigned cpu) */ pending_words =3D xchg_xen_ulong(&vcpu_info->evtchn_pending_sel, 0); =20 - start_word_idx =3D __this_cpu_read(current_word_idx); - start_bit_idx =3D __this_cpu_read(current_bit_idx); + start_word_idx =3D __this_cpu_read(current_word_idx[xh - xenhosts]); + start_bit_idx =3D __this_cpu_read(current_bit_idx[xh - xenhosts]); =20 word_idx =3D start_word_idx; =20 @@ -207,7 +210,7 @@ static void evtchn_2l_handle_events(unsigned cpu) } word_idx =3D EVTCHN_FIRST_BIT(words); =20 - pending_bits =3D active_evtchns(cpu, s, word_idx); + pending_bits =3D active_evtchns(cpu, xh, s, word_idx); bit_idx =3D 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) =20 /* Process port. */ port =3D (word_idx * BITS_PER_EVTCHN_WORD) + bit_idx; - irq =3D get_evtchn_to_irq(port); + irq =3D get_evtchn_to_irq(xh, port); =20 if (irq !=3D -1) generic_handle_irq(irq); @@ -248,10 +251,10 @@ static void evtchn_2l_handle_events(unsigned cpu) bit_idx =3D (bit_idx + 1) % BITS_PER_EVTCHN_WORD; =20 /* 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 !=3D 0); =20 /* 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 =3D xh_default->HYPERVISOR_shared_info; int cpu =3D smp_processor_id(); - xen_ulong_t *cpu_evtchn =3D 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; =20 spin_lock_irqsave(&debug_lock, flags); =20 printk("\nvcpu %d\n ", cpu); =20 - for_each_online_cpu(i) { - int pending; - v =3D per_cpu(xen_vcpu, i); - pending =3D (get_irq_regs() && i =3D=3D cpu) - ? xen_irqs_disabled(get_irq_regs()) - : v->evtchn_upcall_mask; - printk("%d: masked=3D%d pending=3D%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 =3D per_cpu(xen_vcpu, cpu); + for_each_xenhost(xh) { + cpu_evtchn =3D per_cpu(cpu_evtchn_mask, cpu)[(*xh) - xenhosts]; + for_each_online_cpu(i) { + int pending; + v =3D (*xh)->xen_vcpu[i]; + pending =3D (get_irq_regs() && i =3D=3D cpu) + ? xen_irqs_disabled(get_irq_regs()) + : v->evtchn_upcall_mask; + printk("%d: masked=3D%d pending=3D%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 =3D (*xh)->xen_vcpu[cpu]; =20 - printk("\npending:\n "); - for (i =3D ARRAY_SIZE(sh->evtchn_pending)-1; i >=3D 0; i--) - printk("%0*"PRI_xen_ulong"%s", - (int)sizeof(sh->evtchn_pending[0])*2, - sh->evtchn_pending[i], - i % 8 =3D=3D 0 ? "\n " : " "); - printk("\nglobal mask:\n "); - for (i =3D ARRAY_SIZE(sh->evtchn_mask)-1; i >=3D 0; i--) - printk("%0*"PRI_xen_ulong"%s", - (int)(sizeof(sh->evtchn_mask[0])*2), - sh->evtchn_mask[i], - i % 8 =3D=3D 0 ? "\n " : " "); + printk("\npending:\n "); + for (i =3D ARRAY_SIZE(sh->evtchn_pending)-1; i >=3D 0; i--) + printk("%0*"PRI_xen_ulong"%s", + (int)sizeof(sh->evtchn_pending[0])*2, + sh->evtchn_pending[i], + i % 8 =3D=3D 0 ? "\n " : " "); + printk("\nglobal mask:\n "); + for (i =3D ARRAY_SIZE(sh->evtchn_mask)-1; i >=3D 0; i--) + printk("%0*"PRI_xen_ulong"%s", + (int)(sizeof(sh->evtchn_mask[0])*2), + sh->evtchn_mask[i], + i % 8 =3D=3D 0 ? "\n " : " "); =20 - printk("\nglobally unmasked:\n "); - for (i =3D ARRAY_SIZE(sh->evtchn_mask)-1; i >=3D 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 =3D=3D 0 ? "\n " : " "); + printk("\nglobally unmasked:\n "); + for (i =3D ARRAY_SIZE(sh->evtchn_mask)-1; i >=3D 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 =3D=3D 0 ? "\n " : " "); + printk("\nlocal cpu%d mask:\n ", cpu); + for (i =3D (EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD)-1; i >=3D 0; i--) + printk("%0*"PRI_xen_ulong"%s", (int)(sizeof(cpu_evtchn[0])*2), + cpu_evtchn[i], + i % 8 =3D=3D 0 ? "\n " : " "); =20 - printk("\nlocal cpu%d mask:\n ", cpu); - for (i =3D (EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD)-1; i >=3D 0; i--) - printk("%0*"PRI_xen_ulong"%s", (int)(sizeof(cpu_evtchn[0])*2), - cpu_evtchn[i], - i % 8 =3D=3D 0 ? "\n " : " "); + printk("\nlocally unmasked:\n "); + for (i =3D ARRAY_SIZE(sh->evtchn_mask)-1; i >=3D 0; i--) { + xen_ulong_t pending =3D 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 =3D=3D 0 ? "\n " : " "); + } =20 - printk("\nlocally unmasked:\n "); - for (i =3D ARRAY_SIZE(sh->evtchn_mask)-1; i >=3D 0; i--) { - xen_ulong_t pending =3D 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 =3D=3D 0 ? "\n " : " "); - } - - printk("\npending list:\n"); - for (i =3D 0; i < EVTCHN_2L_NR_CHANNELS; i++) { - if (sync_test_bit(i, BM(sh->evtchn_pending))) { - int word_idx =3D 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 =3D 0; i < EVTCHN_2L_NR_CHANNELS; i++) { + if (sync_test_bit(i, BM(sh->evtchn_pending))) { + int word_idx =3D 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"); + } } } =20 @@ -346,12 +352,12 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } =20 -static void evtchn_2l_resume(void) +static void evtchn_2l_resume(xenhost_t *xh) { int i; =20 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); } =20 @@ -369,8 +375,8 @@ static const struct evtchn_ops evtchn_ops_2l =3D { .resume =3D evtchn_2l_resume, }; =20 -void __init xen_evtchn_2l_init(void) +void xen_evtchn_2l_init(xenhost_t *xh) { pr_info("Using 2-level ABI\n"); - evtchn_ops =3D &evtchn_ops_2l; + xh->evtchn_ops =3D &evtchn_ops_2l; } diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_b= ase.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) =3D = {[0 ... NR_VIRQS-1] =3D -1}; /* IRQ <-> IPI mapping */ static DEFINE_PER_CPU(int [XEN_NR_IPIS], ipi_to_irq) =3D {[0 ... XEN_NR_IP= IS-1] =3D -1}; =20 -int **evtchn_to_irq; #ifdef CONFIG_X86 static unsigned long *pirq_eoi_map; #endif static bool (*pirq_needs_eoi)(unsigned irq); =20 -#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))) =20 /* Xen will never allocate port zero for any purpose. */ #define VALID_EVTCHN(chn) ((chn) !=3D 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); =20 -static void clear_evtchn_to_irq_row(unsigned row) +static void clear_evtchn_to_irq_row(xenhost_t *xh, unsigned row) { unsigned col; =20 - for (col =3D 0; col < EVTCHN_PER_ROW; col++) - evtchn_to_irq[row][col] =3D -1; + for (col =3D 0; col < EVTCHN_PER_ROW(xh); col++) + xh->evtchn_to_irq[row][col] =3D -1; } =20 static void clear_evtchn_to_irq_all(void) { unsigned row; + xenhost_t **xh; =20 - for (row =3D 0; row < EVTCHN_ROW(xen_evtchn_max_channels()); row++) { - if (evtchn_to_irq[row] =3D=3D NULL) - continue; - clear_evtchn_to_irq_row(row); + for_each_xenhost(xh) { + for (row =3D 0; row < EVTCHN_ROW(*xh, xen_evtchn_max_channels(*xh)); row= ++) { + if ((*xh)->evtchn_to_irq[row] =3D=3D NULL) + continue; + clear_evtchn_to_irq_row(*xh, row); + } } } =20 -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; =20 - if (evtchn >=3D xen_evtchn_max_channels()) + if (evtchn >=3D xen_evtchn_max_channels(xh)) return -EINVAL; =20 - row =3D EVTCHN_ROW(evtchn); - col =3D EVTCHN_COL(evtchn); + row =3D EVTCHN_ROW(xh, evtchn); + col =3D EVTCHN_COL(xh, evtchn); =20 - if (evtchn_to_irq[row] =3D=3D NULL) { + if (xh->evtchn_to_irq[row] =3D=3D NULL) { /* Unallocated irq entries return -1 anyway */ if (irq =3D=3D -1) return 0; =20 - evtchn_to_irq[row] =3D (int *)get_zeroed_page(GFP_KERNEL); - if (evtchn_to_irq[row] =3D=3D NULL) + xh->evtchn_to_irq[row] =3D (int *)get_zeroed_page(GFP_KERNEL); + if (xh->evtchn_to_irq[row] =3D=3D NULL) return -ENOMEM; =20 - clear_evtchn_to_irq_row(row); + clear_evtchn_to_irq_row(xh, row); } =20 - evtchn_to_irq[row][col] =3D irq; + xh->evtchn_to_irq[row][col] =3D irq; return 0; } =20 -int get_evtchn_to_irq(unsigned evtchn) +int get_evtchn_to_irq(xenhost_t *xh, unsigned evtchn) { - if (evtchn >=3D xen_evtchn_max_channels()) + if (evtchn >=3D xen_evtchn_max_channels(xh)) return -1; - if (evtchn_to_irq[EVTCHN_ROW(evtchn)] =3D=3D NULL) + if (xh->evtchn_to_irq[EVTCHN_ROW(xh, evtchn)] =3D=3D 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)]; } =20 /* Get info for IRQ */ @@ -159,6 +161,7 @@ struct irq_info *info_for_irq(unsigned irq) =20 /* 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 *i= nfo, info->evtchn =3D evtchn; info->cpu =3D cpu; =20 - ret =3D set_evtchn_to_irq(evtchn, irq); + ret =3D set_evtchn_to_irq(xh, evtchn, irq); if (ret < 0) return ret; =20 @@ -182,29 +185,34 @@ static int xen_irq_info_common_setup(struct irq_info = *info, return xen_evtchn_port_setup(info); } =20 -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 =3D info_for_irq(irq); =20 - 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); } =20 -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 =3D info_for_irq(irq); =20 + BUG_ON(xh->type !=3D xenhost_r1); + info->u.ipi =3D ipi; =20 per_cpu(ipi_to_irq, cpu)[ipi] =3D irq; =20 - 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); } =20 -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, =20 per_cpu(virq_to_irq, cpu)[virq] =3D irq; =20 - 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); } =20 -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 =3D domid; info->u.pirq.flags =3D flags; =20 - 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); } =20 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 =3D 0; } =20 @@ -252,9 +261,9 @@ unsigned int evtchn_from_irq(unsigned irq) return info_for_irq(irq)->evtchn; } =20 -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); =20 @@ -303,9 +312,9 @@ unsigned cpu_from_irq(unsigned irq) return info_for_irq(irq)->cpu; } =20 -unsigned int cpu_from_evtchn(unsigned int evtchn) +unsigned int cpu_from_evtchn(xenhost_t *xh, unsigned int evtchn) { - int irq =3D get_evtchn_to_irq(evtchn); + int irq =3D get_evtchn_to_irq(xh, evtchn); unsigned ret =3D 0; =20 if (irq !=3D -1) @@ -329,9 +338,9 @@ static bool pirq_needs_eoi_flag(unsigned irq) return info->u.pirq.flags & PIRQ_NEEDS_EOI; } =20 -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 i= nt cpu) { - int irq =3D get_evtchn_to_irq(chn); + int irq =3D get_evtchn_to_irq(xh, chn); struct irq_info *info =3D info_for_irq(irq); =20 BUG_ON(irq =3D=3D -1); @@ -356,11 +365,11 @@ void notify_remote_via_irq(int irq) int evtchn =3D evtchn_from_irq(irq); =20 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); =20 -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) =20 info->type =3D IRQT_UNBOUND; info->refcnt =3D -1; + info->xh =3D xh; =20 irq_set_handler_data(irq, info); =20 list_add_tail(&info->list, &xen_irq_list_head); } =20 -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 =3D irq_alloc_descs(-1, 0, nvec, -1); =20 if (irq >=3D 0) { for (i =3D 0; i < nvec; i++) - xen_irq_init(irq + i); + xen_irq_init(xh, irq + i); } =20 return irq; } =20 -static inline int __must_check xen_allocate_irq_dynamic(void) +static inline int __must_check xen_allocate_irq_dynamic(xenhost_t *xh) { =20 - return xen_allocate_irqs_dynamic(1); + return xen_allocate_irqs_dynamic(xh, 1); } =20 -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; =20 @@ -409,7 +419,7 @@ static int __must_check xen_allocate_irq_gsi(unsigned g= si) * space. */ if (xen_pv_domain() && !xen_initial_domain()) - return xen_allocate_irq_dynamic(); + return xen_allocate_irq_dynamic(xh); =20 /* 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 g= si) else irq =3D irq_alloc_desc_at(gsi, -1); =20 - xen_irq_init(irq); + xen_irq_init(xh, irq); =20 return irq; } @@ -444,12 +454,12 @@ static void xen_free_irq(unsigned irq) irq_free_desc(irq); } =20 -static void xen_evtchn_close(unsigned int port) +static void xen_evtchn_close(xenhost_t *xh, unsigned int port) { struct evtchn_close close; =20 close.port =3D port; - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) !=3D 0) + if (hypervisor_event_channel_op(xh, EVTCHNOP_close, &close) !=3D 0) BUG(); } =20 @@ -473,6 +483,7 @@ static void eoi_pirq(struct irq_data *data) { int evtchn =3D evtchn_from_irq(data->irq); struct physdev_eoi eoi =3D { .irq =3D pirq_from_irq(data->irq) }; + xenhost_t *xh =3D info_for_irq(data->irq)->xh; int rc =3D 0; =20 if (!VALID_EVTCHN(evtchn)) @@ -480,16 +491,16 @@ static void eoi_pirq(struct irq_data *data) =20 if (unlikely(irqd_is_setaffinity_pending(data)) && likely(!irqd_irq_disabled(data))) { - int masked =3D test_and_set_mask(evtchn); + int masked =3D test_and_set_mask(xh, evtchn); =20 - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); =20 irq_move_masked_irq(data); =20 if (!masked) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); } else - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); =20 if (pirq_needs_eoi(data->irq)) { rc =3D 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 =3D info->u.pirq.flags & PIRQ_SHAREABLE ? BIND_PIRQ__WILL_SHARE : 0; - rc =3D HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq); + rc =3D hypervisor_event_channel_op(info->xh, EVTCHNOP_bind_pirq, &bind_pi= rq); if (rc !=3D 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) =20 pirq_query_unmask(irq); =20 - rc =3D set_evtchn_to_irq(evtchn, irq); + rc =3D set_evtchn_to_irq(info->xh, evtchn, irq); if (rc) goto err; =20 info->evtchn =3D evtchn; - bind_evtchn_to_cpu(evtchn, 0); + bind_evtchn_to_cpu(info->xh, evtchn, 0); =20 rc =3D xen_evtchn_port_setup(info); if (rc) goto err; =20 out: - unmask_evtchn(evtchn); + unmask_evtchn(info->xh, evtchn); eoi_pirq(irq_get_irq_data(irq)); =20 return 0; =20 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; } =20 @@ -567,8 +578,8 @@ static void shutdown_pirq(struct irq_data *data) if (!VALID_EVTCHN(evtchn)) return; =20 - mask_evtchn(evtchn); - xen_evtchn_close(evtchn); + mask_evtchn(info->xh, evtchn); + xen_evtchn_close(info->xh, evtchn); xen_irq_info_cleanup(info); } =20 @@ -612,7 +623,7 @@ static void __unbind_from_irq(unsigned int irq) if (VALID_EVTCHN(evtchn)) { unsigned int cpu =3D cpu_from_irq(irq); =20 - xen_evtchn_close(evtchn); + xen_evtchn_close(info->xh, evtchn); =20 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 =3D -1; struct physdev_irq irq_op; int ret; =20 + BUG_ON(xh->type !=3D xenhost_r1); + mutex_lock(&irq_mapping_update_lock); =20 irq =3D xen_irq_from_gsi(gsi); @@ -657,7 +670,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, goto out; } =20 - irq =3D xen_allocate_irq_gsi(gsi); + irq =3D xen_allocate_irq_gsi(xh, gsi); if (irq < 0) goto out; =20 @@ -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 =3D -ENOSPC; goto out; } =20 - ret =3D xen_irq_info_pirq_setup(irq, 0, pirq, gsi, DOMID_SELF, + ret =3D 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, } =20 #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_d= esc *msidesc) { int rc; struct physdev_get_free_pirq op_get_free_pirq; =20 op_get_free_pirq.type =3D MAP_PIRQ_TYPE_MSI; - rc =3D HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); + rc =3D hypervisor_physdev_op(xh, PHYSDEVOP_get_free_pirq, &op_get_free_pi= rq); =20 WARN_ONCE(rc =3D=3D -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; } =20 -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 ms= i_desc *msidesc, int pirq, int nvec, const char *name, domid_t domid) { int i, irq, ret; =20 mutex_lock(&irq_mapping_update_lock); =20 - irq =3D xen_allocate_irqs_dynamic(nvec); + irq =3D xen_allocate_irqs_dynamic(xh, nvec); if (irq < 0) goto out; =20 for (i =3D 0; i < nvec; i++) { irq_set_chip_and_handler_name(irq + i, &xen_pirq_chip, handle_edge_irq, = name); =20 - ret =3D xen_irq_info_pirq_setup(irq + i, 0, pirq + i, 0, domid, + ret =3D xen_irq_info_pirq_setup(xh, irq + i, 0, pirq + i, 0, domid, i =3D=3D 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 =3D info->u.pirq.pirq; unmap_irq.domid =3D info->u.pirq.domid; - rc =3D HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); + rc =3D 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); =20 -int bind_evtchn_to_irq(unsigned int evtchn) +int bind_evtchn_to_irq(xenhost_t *xh, unsigned int evtchn) { int irq; int ret; =20 - if (evtchn >=3D xen_evtchn_max_channels()) + if (evtchn >=3D xen_evtchn_max_channels(xh)) return -ENOMEM; =20 mutex_lock(&irq_mapping_update_lock); =20 - irq =3D get_evtchn_to_irq(evtchn); + irq =3D get_evtchn_to_irq(xh, evtchn); =20 if (irq =3D=3D -1) { - irq =3D xen_allocate_irq_dynamic(); + irq =3D xen_allocate_irq_dynamic(xh); if (irq < 0) goto out; =20 irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, handle_edge_irq, "event"); =20 - ret =3D xen_irq_info_evtchn_setup(irq, evtchn); + ret =3D xen_irq_info_evtchn_setup(xh, irq, evtchn); if (ret < 0) { __unbind_from_irq(irq); irq =3D 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 =3D info_for_irq(irq); WARN_ON(info =3D=3D NULL || info->type !=3D IRQT_EVTCHN); @@ -866,37 +879,39 @@ int bind_evtchn_to_irq(unsigned int evtchn) } EXPORT_SYMBOL_GPL(bind_evtchn_to_irq); =20 -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 c= pu) { struct evtchn_bind_ipi bind_ipi; int evtchn, irq; int ret; =20 + BUG_ON(xh->type =3D=3D xenhost_r2); + mutex_lock(&irq_mapping_update_lock); =20 irq =3D per_cpu(ipi_to_irq, cpu)[ipi]; =20 if (irq =3D=3D -1) { - irq =3D xen_allocate_irq_dynamic(); + irq =3D xen_allocate_irq_dynamic(xh); if (irq < 0) goto out; =20 irq_set_chip_and_handler_name(irq, &xen_percpu_chip, handle_percpu_irq, "ipi"); =20 - bind_ipi.vcpu =3D xen_vcpu_nr(xh_default, cpu); - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, + bind_ipi.vcpu =3D xen_vcpu_nr(xh, cpu); + if (hypervisor_event_channel_op(xh, EVTCHNOP_bind_ipi, &bind_ipi) !=3D 0) BUG(); evtchn =3D bind_ipi.port; =20 - ret =3D xen_irq_info_ipi_setup(cpu, irq, evtchn, ipi); + ret =3D xen_irq_info_ipi_setup(xh, cpu, irq, evtchn, ipi); if (ret < 0) { __unbind_from_irq(irq); irq =3D ret; goto out; } - bind_evtchn_to_cpu(evtchn, cpu); + bind_evtchn_to_cpu(xh, evtchn, cpu); } else { struct irq_info *info =3D info_for_irq(irq); WARN_ON(info =3D=3D NULL || info->type !=3D IRQT_IPI); @@ -907,7 +922,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned i= nt cpu) return irq; } =20 -int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, +int bind_interdomain_evtchn_to_irq(xenhost_t *xh, unsigned int remote_doma= in, unsigned int remote_port) { struct evtchn_bind_interdomain bind_interdomain; @@ -916,28 +931,28 @@ int bind_interdomain_evtchn_to_irq(unsigned int remot= e_domain, bind_interdomain.remote_dom =3D remote_domain; bind_interdomain.remote_port =3D remote_port; =20 - err =3D HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, + err =3D hypervisor_event_channel_op(xh, EVTCHNOP_bind_interdomain, &bind_interdomain); =20 - 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); =20 -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 =3D -ENOENT; =20 memset(&status, 0, sizeof(status)); - for (port =3D 0; port < xen_evtchn_max_channels(); port++) { + for (port =3D 0; port < xen_evtchn_max_channels(xh); port++) { status.dom =3D DOMID_SELF; status.port =3D port; - rc =3D HYPERVISOR_event_channel_op(EVTCHNOP_status, &status); + rc =3D hypervisor_event_channel_op(xh, EVTCHNOP_status, &status); if (rc < 0) continue; if (status.status !=3D EVTCHNSTAT_virq) continue; - if (status.u.virq =3D=3D virq && status.vcpu =3D=3D xen_vcpu_nr(xh_defau= lt, cpu)) { + if (status.u.virq =3D=3D virq && status.vcpu =3D=3D xen_vcpu_nr(xh, cpu)= ) { rc =3D 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); =20 -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, b= ool 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 cp= u, bool percpu) irq =3D per_cpu(virq_to_irq, cpu)[virq]; =20 if (irq =3D=3D -1) { - irq =3D xen_allocate_irq_dynamic(); + irq =3D xen_allocate_irq_dynamic(xh); if (irq < 0) goto out; =20 @@ -980,26 +995,26 @@ int bind_virq_to_irq(unsigned int virq, unsigned int = cpu, bool percpu) handle_edge_irq, "virq"); =20 bind_virq.virq =3D virq; - bind_virq.vcpu =3D xen_vcpu_nr(xh_default, cpu); - ret =3D HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, + bind_virq.vcpu =3D xen_vcpu_nr(xh, cpu); + ret =3D hypervisor_event_channel_op(xh, EVTCHNOP_bind_virq, &bind_virq); if (ret =3D=3D 0) evtchn =3D bind_virq.port; else { if (ret =3D=3D -EEXIST) - ret =3D find_virq(virq, cpu); + ret =3D find_virq(xh, virq, cpu); BUG_ON(ret < 0); evtchn =3D ret; } =20 - ret =3D xen_irq_info_virq_setup(cpu, irq, evtchn, virq); + ret =3D xen_irq_info_virq_setup(xh, cpu, irq, evtchn, virq); if (ret < 0) { __unbind_from_irq(irq); irq =3D ret; goto out; } =20 - bind_evtchn_to_cpu(evtchn, cpu); + bind_evtchn_to_cpu(xh, evtchn, cpu); } else { struct irq_info *info =3D info_for_irq(irq); WARN_ON(info =3D=3D NULL || info->type !=3D IRQT_VIRQ); @@ -1018,14 +1033,15 @@ static void unbind_from_irq(unsigned int irq) mutex_unlock(&irq_mapping_update_lock); } =20 -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; =20 - irq =3D bind_evtchn_to_irq(evtchn); + irq =3D bind_evtchn_to_irq(xh, evtchn); if (irq < 0) return irq; retval =3D 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); =20 -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 in= t remote_domain, { int irq, retval; =20 - irq =3D bind_interdomain_evtchn_to_irq(remote_domain, remote_port); + irq =3D bind_interdomain_evtchn_to_irq(xh, remote_domain, remote_port); if (irq < 0) return irq; =20 @@ -1061,13 +1078,14 @@ int bind_interdomain_evtchn_to_irqhandler(unsigned = int remote_domain, } EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irqhandler); =20 -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; =20 - irq =3D bind_virq_to_irq(virq, cpu, irqflags & IRQF_PERCPU); + irq =3D bind_virq_to_irq(xh, virq, cpu, irqflags & IRQF_PERCPU); if (irq < 0) return irq; retval =3D request_irq(irq, handler, irqflags, devname, dev_id); @@ -1080,7 +1098,8 @@ int bind_virq_to_irqhandler(unsigned int virq, unsign= ed int cpu, } EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler); =20 -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; =20 - irq =3D bind_ipi_to_irq(ipi, cpu); + irq =3D bind_ipi_to_irq(xh, ipi, cpu); if (irq < 0) return irq; =20 @@ -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_M= IN. */ -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; =20 set_priority.port =3D evtchn_from_irq(irq); set_priority.priority =3D priority; =20 - 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); =20 -int evtchn_make_refcounted(unsigned int evtchn) +int evtchn_make_refcounted(xenhost_t *xh, unsigned int evtchn) { - int irq =3D get_evtchn_to_irq(evtchn); + int irq =3D get_evtchn_to_irq(xh, evtchn); struct irq_info *info; =20 if (irq =3D=3D -1) @@ -1152,18 +1171,18 @@ int evtchn_make_refcounted(unsigned int evtchn) } EXPORT_SYMBOL_GPL(evtchn_make_refcounted); =20 -int evtchn_get(unsigned int evtchn) +int evtchn_get(xenhost_t *xh, unsigned int evtchn) { int irq; struct irq_info *info; int err =3D -ENOENT; =20 - if (evtchn >=3D xen_evtchn_max_channels()) + if (evtchn >=3D xen_evtchn_max_channels(xh)) return -EINVAL; =20 mutex_lock(&irq_mapping_update_lock); =20 - irq =3D get_evtchn_to_irq(evtchn); + irq =3D get_evtchn_to_irq(xh, evtchn); if (irq =3D=3D -1) goto done; =20 @@ -1185,22 +1204,22 @@ int evtchn_get(unsigned int evtchn) } EXPORT_SYMBOL_GPL(evtchn_get); =20 -void evtchn_put(unsigned int evtchn) +void evtchn_put(xenhost_t *xh, unsigned int evtchn) { - int irq =3D get_evtchn_to_irq(evtchn); + int irq =3D get_evtchn_to_irq(xh, evtchn); if (WARN_ON(irq =3D=3D -1)) return; unbind_from_irq(irq); } EXPORT_SYMBOL_GPL(evtchn_put); =20 -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 vec= tor) { int irq; =20 #ifdef CONFIG_X86 if (unlikely(vector =3D=3D XEN_NMI_VECTOR)) { - int rc =3D HYPERVISOR_vcpu_op(VCPUOP_send_nmi, xen_vcpu_nr(xh_default, = cpu), + int rc =3D 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); =20 static void __xen_evtchn_do_upcall(void) { - struct vcpu_info *vcpu_info =3D __this_cpu_read(xen_vcpu); int cpu =3D get_cpu(); unsigned count; + xenhost_t **xh; =20 - do { - vcpu_info->evtchn_upcall_pending =3D 0; + for_each_xenhost(xh) { + struct vcpu_info *vcpu_info =3D (*xh)->xen_vcpu[cpu]; + do { + vcpu_info->evtchn_upcall_pending =3D 0; =20 - if (__this_cpu_inc_return(xed_nesting_count) - 1) - goto out; + if (__this_cpu_inc_return(xed_nesting_count) - 1) + goto out; =20 - xen_evtchn_handle_events(cpu); + xen_evtchn_handle_events(*xh, cpu); =20 - BUG_ON(!irqs_disabled()); + BUG_ON(!irqs_disabled()); =20 - count =3D __this_cpu_read(xed_nesting_count); - __this_cpu_write(xed_nesting_count, 0); - } while (count !=3D 1 || vcpu_info->evtchn_upcall_pending); + count =3D __this_cpu_read(xed_nesting_count); + __this_cpu_write(xed_nesting_count, 0); + } while (count !=3D 1 || vcpu_info->evtchn_upcall_pending); + } =20 out: =20 @@ -1275,16 +1297,16 @@ void rebind_evtchn_irq(int evtchn, int irq) mutex_lock(&irq_mapping_update_lock); =20 /* After resume the irq<->evtchn mappings are all cleared out */ - BUG_ON(get_evtchn_to_irq(evtchn) !=3D -1); + BUG_ON(get_evtchn_to_irq(info->xh, evtchn) !=3D -1); /* Expect irq to have been bound before, so there should be a proper type */ BUG_ON(info->type =3D=3D IRQT_UNBOUND); =20 - (void)xen_irq_info_evtchn_setup(irq, evtchn); + (void)xen_irq_info_evtchn_setup(info->xh, irq, evtchn); =20 mutex_unlock(&irq_mapping_update_lock); =20 - 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)); =20 @@ -1293,7 +1315,7 @@ void rebind_evtchn_irq(int evtchn, int irq) } =20 /* 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 t= cpu) =20 /* Send future instances of this interrupt to other vcpu. */ bind_vcpu.port =3D evtchn; - bind_vcpu.vcpu =3D xen_vcpu_nr(xh_default, tcpu); + bind_vcpu.vcpu =3D xen_vcpu_nr(xh, tcpu); =20 /* * Mask the event while changing the VCPU binding to prevent * it being delivered on an unexpected VCPU. */ - masked =3D test_and_set_mask(evtchn); + masked =3D test_and_set_mask(xh, evtchn); =20 /* * 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) >=3D 0) - bind_evtchn_to_cpu(evtchn, tcpu); + if (hypervisor_event_channel_op(xh, EVTCHNOP_bind_vcpu, &bind_vcpu) >=3D = 0) + bind_evtchn_to_cpu(xh, evtchn, tcpu); =20 if (!masked) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); =20 return 0; } @@ -1333,7 +1355,10 @@ static int set_affinity_irq(struct irq_data *data, c= onst struct cpumask *dest, bool force) { unsigned tcpu =3D cpumask_first_and(dest, cpu_online_mask); - int ret =3D xen_rebind_evtchn_to_cpu(evtchn_from_irq(data->irq), tcpu); + xenhost_t *xh =3D info_for_irq(data->irq)->xh; + int ret; + + ret =3D xen_rebind_evtchn_to_cpu(xh, evtchn_from_irq(data->irq), tcpu); =20 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 =3D evtchn_from_irq(data->irq); + xenhost_t *xh =3D info_for_irq(data->irq)->xh; =20 if (VALID_EVTCHN(evtchn)) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); } =20 static void disable_dynirq(struct irq_data *data) { int evtchn =3D evtchn_from_irq(data->irq); + xenhost_t *xh =3D info_for_irq(data->irq)->xh; =20 if (VALID_EVTCHN(evtchn)) - mask_evtchn(evtchn); + mask_evtchn(xh, evtchn); } =20 static void ack_dynirq(struct irq_data *data) { int evtchn =3D evtchn_from_irq(data->irq); + xenhost_t *xh =3D info_for_irq(data->irq)->xh; =20 if (!VALID_EVTCHN(evtchn)) return; =20 if (unlikely(irqd_is_setaffinity_pending(data)) && likely(!irqd_irq_disabled(data))) { - int masked =3D test_and_set_mask(evtchn); + int masked =3D test_and_set_mask(xh, evtchn); =20 - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); =20 irq_move_masked_irq(data); =20 if (!masked) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); } else - clear_evtchn(evtchn); + clear_evtchn(xh, evtchn); } =20 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 =3D evtchn_from_irq(data->irq); + xenhost_t *xh =3D info_for_irq(data->irq)->xh; int masked; =20 if (!VALID_EVTCHN(evtchn)) return 0; =20 - masked =3D test_and_set_mask(evtchn); - set_evtchn(evtchn); + masked =3D test_and_set_mask(xh, evtchn); + set_evtchn(xh, evtchn); if (!masked) - unmask_evtchn(evtchn); + unmask_evtchn(xh, evtchn); =20 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; =20 for (virq =3D 0; virq < NR_VIRQS; virq++) { if ((irq =3D per_cpu(virq_to_irq, cpu)[virq]) =3D=3D -1) continue; + xh =3D info_for_irq(irq)->xh; =20 BUG_ON(virq_from_irq(irq) !=3D virq); =20 /* Get a new binding from Xen. */ bind_virq.virq =3D virq; bind_virq.vcpu =3D 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) !=3D 0) BUG(); evtchn =3D bind_virq.port; =20 /* 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); } } =20 @@ -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; =20 for (ipi =3D 0; ipi < XEN_NR_IPIS; ipi++) { if ((irq =3D per_cpu(ipi_to_irq, cpu)[ipi]) =3D=3D -1) continue; + xh =3D info_for_irq(irq)->xh; =20 BUG_ON(ipi_from_irq(irq) !=3D ipi); =20 /* Get a new binding from Xen. */ - bind_ipi.vcpu =3D xen_vcpu_nr(xh_default, cpu); - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, + bind_ipi.vcpu =3D xen_vcpu_nr(xh, cpu); + if (hypervisor_event_channel_op(xh, EVTCHNOP_bind_ipi, &bind_ipi) !=3D 0) BUG(); evtchn =3D bind_ipi.port; =20 /* 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); } } =20 @@ -1491,26 +1524,29 @@ static void restore_cpu_ipis(unsigned int cpu) void xen_clear_irq_pending(int irq) { int evtchn =3D evtchn_from_irq(irq); + xenhost_t *xh =3D info_for_irq(irq)->xh; =20 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 =3D evtchn_from_irq(irq); + xenhost_t *xh =3D info_for_irq(irq)->xh; =20 if (VALID_EVTCHN(evtchn)) - set_evtchn(evtchn); + set_evtchn(xh, evtchn); } =20 bool xen_test_irq_pending(int irq) { int evtchn =3D evtchn_from_irq(irq); + xenhost_t *xh =3D info_for_irq(irq)->xh; bool ret =3D false; =20 if (VALID_EVTCHN(evtchn)) - ret =3D test_evtchn(evtchn); + ret =3D test_evtchn(xh, evtchn); =20 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 =3D evtchn_from_irq(irq); + xenhost_t *xh =3D info_for_irq(irq)->xh; =20 if (VALID_EVTCHN(evtchn)) { struct sched_poll poll; =20 + BUG_ON(xh->type !=3D xenhost_r1); + poll.nr_ports =3D 1; poll.timeout =3D timeout; set_xen_guest_handle(poll.ports, &evtchn); @@ -1665,26 +1704,30 @@ void xen_callback_vector(void) {} static bool fifo_events =3D true; module_param(fifo_events, bool, 0); =20 -void __init xen_init_IRQ(void) +void xen_init_IRQ(xenhost_t *xh) { int ret =3D -EINVAL; unsigned int evtchn; =20 - if (fifo_events) - ret =3D xen_evtchn_fifo_init(); if (ret < 0) - xen_evtchn_2l_init(); + xen_evtchn_2l_init(xh); =20 - evtchn_to_irq =3D kcalloc(EVTCHN_ROW(xen_evtchn_max_channels()), - sizeof(*evtchn_to_irq), GFP_KERNEL); - BUG_ON(!evtchn_to_irq); + xh->evtchn_to_irq =3D kcalloc(EVTCHN_ROW(xh, xen_evtchn_max_channels(xh)), + sizeof(*(xh->evtchn_to_irq)), GFP_KERNEL); + BUG_ON(!xh->evtchn_to_irq); =20 /* No event channels are 'live' right now. */ - for (evtchn =3D 0; evtchn < xen_evtchn_nr_channels(); evtchn++) - mask_evtchn(evtchn); + for (evtchn =3D 0; evtchn < xen_evtchn_nr_channels(xh); evtchn++) + mask_evtchn(xh, evtchn); =20 pirq_needs_eoi =3D pirq_needs_eoi_flag; =20 + /* + * Callback vectors, HW irqs are only for xenhost_r1 + */ + if (xh->type !=3D 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_f= ifo.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] =3D head; } =20 -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/even= ts_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) =20 struct evtchn_ops { - unsigned (*max_channels)(void); - unsigned (*nr_channels)(void); + unsigned (*max_channels)(xenhost_t *xh); + unsigned (*nr_channels)(xenhost_t *xh); =20 int (*setup)(struct irq_info *info); void (*bind_to_cpu)(struct irq_info *info, unsigned cpu); =20 - 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); =20 - void (*handle_events)(unsigned cpu); - void (*resume)(void); + void (*handle_events)(xenhost_t *xh, unsigned cpu); + void (*resume)(xenhost_t *xh); }; =20 -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); =20 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); =20 -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); } =20 /* @@ -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; } =20 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); } =20 -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); } =20 -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); } =20 -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); } =20 -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); } =20 -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); } =20 -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); } =20 -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); } =20 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); } =20 -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); =20 #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 ch= ar __user *buf, evtchn =3D find_evtchn(u, port); if (evtchn && !evtchn->enabled) { evtchn->enabled =3D true; - enable_irq(irq_from_evtchn(port)); + enable_irq(irq_from_evtchn(xh_default, port)); } } =20 @@ -392,18 +392,18 @@ static int evtchn_bind_to_user(struct per_user_data *= u, int port) if (rc < 0) goto err; =20 - rc =3D bind_evtchn_to_irqhandler(port, evtchn_interrupt, 0, + rc =3D bind_evtchn_to_irqhandler(xh_default, port, evtchn_interrupt, 0, u->name, evtchn); if (rc < 0) goto err; =20 - rc =3D evtchn_make_refcounted(port); + rc =3D evtchn_make_refcounted(xh_default, port); return rc; =20 err: /* bind failed, should close the port now */ close.port =3D port; - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) !=3D 0) + if (hypervisor_event_channel_op(xh_default, EVTCHNOP_close, &close) !=3D = 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 =3D irq_from_evtchn(evtchn->port); + int irq =3D irq_from_evtchn(xh_default, evtchn->port); =20 BUG_ON(irq < 0); =20 @@ -429,7 +429,7 @@ static void evtchn_bind_interdom_next_vcpu(int evtchn) struct irq_desc *desc; unsigned long flags; =20 - irq =3D irq_from_evtchn(evtchn); + irq =3D irq_from_evtchn(xh_default, evtchn); desc =3D irq_to_desc(irq); =20 if (!desc) @@ -447,7 +447,7 @@ static void evtchn_bind_interdom_next_vcpu(int evtchn) this_cpu_write(bind_last_selected_cpu, selected_cpu); =20 /* 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); } =20 @@ -549,7 +549,7 @@ static long evtchn_ioctl(struct file *file, break; =20 rc =3D -EINVAL; - if (unbind.port >=3D xen_evtchn_nr_channels()) + if (unbind.port >=3D xen_evtchn_nr_channels(xh_default)) break; =20 rc =3D -ENOTCONN; @@ -557,7 +557,7 @@ static long evtchn_ioctl(struct file *file, if (!evtchn) break; =20 - disable_irq(irq_from_evtchn(unbind.port)); + disable_irq(irq_from_evtchn(xh_default, unbind.port)); evtchn_unbind_from_user(u, evtchn); rc =3D 0; break; @@ -574,7 +574,7 @@ static long evtchn_ioctl(struct file *file, rc =3D -ENOTCONN; evtchn =3D find_evtchn(u, notify.port); if (evtchn) { - notify_remote_via_evtchn(notify.port); + notify_remote_via_evtchn(xh_default, notify.port); rc =3D 0; } break; @@ -676,7 +676,7 @@ static int evtchn_release(struct inode *inode, struct f= ile *filp) struct user_evtchn *evtchn; =20 evtchn =3D 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); } =20 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 #include #include +#include #include #include =20 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); } =20 gref->notify.flags =3D 0; @@ -418,14 +418,14 @@ static long gntalloc_ioctl_unmap_notify(struct gntall= oc_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 =3D -EINVAL; goto unlock_out; } } =20 if (gref->notify.flags & UNMAP_NOTIFY_SEND_EVENT) - evtchn_put(gref->notify.event); + evtchn_put(xh_default, gref->notify.event); =20 gref->notify.flags =3D op.action; gref->notify.pgoff =3D 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 gn= tdev_grant_map *map) atomic_sub(map->count, &pages_mapped); =20 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); } =20 if (populate_freeable_maps && priv) { @@ -790,7 +790,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *pri= v, 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; } =20 @@ -829,7 +829,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *pri= v, void __user *u) =20 /* 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); =20 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; } =20 - ret =3D bind_virq_to_irqhandler(VIRQ_MCA, 0, + ret =3D 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; =20 - irq =3D bind_virq_to_irqhandler(VIRQ_PCPU_STATE, 0, + irq =3D 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 @@ */ =20 #include +#include #include =20 #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 #include #include +#include #include #include =20 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 #include =20 +#include #include #include =20 #include #include -#include #include #ifdef CONFIG_XEN_HAVE_VPMU #include 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 #include =20 +#include #include #include #include =20 #include #include -#include #include #include =20 diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xen= bus.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, =20 pdev->sh_info =3D vaddr; =20 - err =3D bind_interdomain_evtchn_to_irqhandler( + err =3D 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 #include =20 + +#include #include - #include #include #include @@ -829,7 +830,7 @@ static int scsiback_init_sring(struct vscsibk_info *inf= o, grant_ref_t ring_ref, sring =3D (struct vscsiif_sring *)area; BACK_RING_INIT(&info->ring, sring, PAGE_SIZE); =20 - err =3D bind_interdomain_evtchn_to_irq(info->domid, evtchn); + err =3D bind_interdomain_evtchn_to_irq(xh_default, info->domid, evtchn); if (err < 0) goto unmap_page; =20 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 #include #include -#include #include #include +#include #include #include #include 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) =20 /* Implies mb(): other side will see the updated producer. */ if (prod <=3D intf->req_cons) - notify_remote_via_evtchn(xen_store_evtchn); + notify_remote_via_evtchn(xh_default, xen_store_evtchn); } =20 return bytes; @@ -204,7 +204,7 @@ static int xb_read(void *data, unsigned int len) =20 /* Implies mb(): other side will see the updated consumer. */ if (intf->rsp_prod - cons >=3D XENSTORE_RING_SIZE) - notify_remote_via_evtchn(xen_store_evtchn); + notify_remote_via_evtchn(xh_default, xen_store_evtchn); } =20 return bytes; @@ -461,7 +461,7 @@ int xb_init_comms(void) } else { int err; =20 - err =3D bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting, + err =3D bind_evtchn_to_irqhandler(xh_default, xen_store_evtchn, wake_wai= ting, 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 @@ =20 #include #include +#include #include =20 #include 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 @@ =20 #include #include +#include #include #include #include diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbu= s/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 @@ =20 #include #include +#include #include #include #include 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 #include #include +#include #include #include #include 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 #include =20 -unsigned xen_evtchn_nr_channels(void); +unsigned xen_evtchn_nr_channels(xenhost_t *xh); =20 -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, b= ool 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); =20 /* * 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); =20 -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 vec= tor); 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); =20 -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 =3D { .port =3D port }; - (void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); + (void)hypervisor_event_channel_op(xh, EVTCHNOP_send, &send); } =20 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); =20 /* 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); =20 @@ -101,14 +104,14 @@ void xen_evtchn_do_upcall(struct pt_regs *regs); void xen_hvm_evtchn_do_upcall(void); =20 /* 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); =20 #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_d= esc *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 ms= i_desc *msidesc, int pirq, int nvec, const char *name, domid_t domid); #endif =20 @@ -128,5 +131,5 @@ int xen_irq_from_gsi(unsigned gsi); int xen_test_irq_shared(int irq); =20 /* 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; =20 typedef struct xenhost_ops { --=20 2.20.1 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel