From patchwork Tue Apr 18 09:14:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Roger_Pau_Monn=C3=A9?= X-Patchwork-Id: 9685225 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 05C33602C2 for ; Tue, 18 Apr 2017 09:17:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D6F8528388 for ; Tue, 18 Apr 2017 09:17:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C7E99283F9; Tue, 18 Apr 2017 09:17:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 30C3A28388 for ; Tue, 18 Apr 2017 09:17:49 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d0PEB-00089B-Pt; Tue, 18 Apr 2017 09:15:15 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d0PEA-000895-8M for xen-devel@lists.xenproject.org; Tue, 18 Apr 2017 09:15:14 +0000 Received: from [85.158.137.68] by server-5.bemta-3.messagelabs.com id 6C/0C-02185-129D5F85; Tue, 18 Apr 2017 09:15:13 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprIIsWRWlGSWpSXmKPExsXitHRDpK7Cza8 RBn/eW1p83zKZyYHR4/CHKywBjFGsmXlJ+RUJrBkPJ05gLDhhWnGpYR9jA2OnRhcjJ4eEgL/E zxWH2UBsNgEdiYtzdwLZHBwiAioSt/cadDFycTAL7GGUONR+BaxGWCBI4t6cmYwgNouAqsTvV YdZQWxeAUuJXUfXMUPM1JN4O/EFI0RcUOLkzCcsIDazgKZE6/bf7BC2vETz1tlg9UICihL98x 6wTWDkmYWkZRaSlllIWhYwMq9i1ChOLSpLLdI1MtRLKspMzyjJTczM0TU0MNbLTS0uTkxPzUl MKtZLzs/dxAgMnnoGBsYdjD17/Q4xSnIwKYny/rL4GiHEl5SfUpmRWJwRX1Sak1p8iFGDg0Ng 89rVFxilWPLy81KVJHg7rwPVCRalpqdWpGXmAMMbplSCg0dJhJfvBlCat7ggMbc4Mx0idYpRU Uqc98M1oIQASCKjNA+uDRZTlxhlpYR5GRkYGIR4ClKLcjNLUOVfMYpzMCoJ8xaAbOfJzCuBm/ 4KaDET0OKIgC8gi0sSEVJSDYwCSg/n/kr48fBqtgrvDdGs9fp9GR0z5Etf7tJc2ns6x1W4fKq CX3KJtbEcw94Y082XOJNCplWzT50/aTZnbpD0nTLrwJI21UKxrR7BF746rdnAn3SZe7HGo8hv F4vO3pbXExS/YyjfWPXWRElk8V8udS6h2HUfvW6ot7GxHY81fJex/b/uOiWW4oxEQy3mouJEA Ftk2PSkAgAA X-Env-Sender: prvs=274ddec60=roger.pau@citrix.com X-Msg-Ref: server-5.tower-31.messagelabs.com!1492506911!92882973!1 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.4.12; banners=-,-,- X-VirusChecked: Checked Received: (qmail 3126 invoked from network); 18 Apr 2017 09:15:12 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-5.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 18 Apr 2017 09:15:12 -0000 X-IronPort-AV: E=Sophos;i="5.37,218,1488844800"; d="scan'208";a="419581019" From: Roger Pau Monne To: Date: Tue, 18 Apr 2017 10:14:02 +0100 Message-ID: <20170418091402.78489-1-roger.pau@citrix.com> X-Mailer: git-send-email 2.11.0 (Apple Git-81) MIME-Version: 1.0 Cc: Andrew Cooper , Julien Grall , Chao Gao , Jan Beulich , Roger Pau Monne Subject: [Xen-devel] [PATCH for-4.9 v2] x86/vioapic: allow holes in the GSI range for PVH Dom0 X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP The current vIO APIC for PVH Dom0 doesn't allow non-contiguous GSIs, which means that all GSIs must belong to an IO APIC. This doesn't match reality, where there are systems with non-contiguous GSIs. In order to fix this add a base_gsi field to each hvm_vioapic struct, in order to store the base GSI for each emulated IO APIC. For PVH Dom0 those values are populated based on the hardware ones. Signed-off-by: Roger Pau Monné Reported-by: Chao Gao --- Cc: Jan Beulich Cc: Andrew Cooper Cc: Julien Grall Cc: Chao Gao --- Changes since v1: - Calculate the maximum GSI in vioapic_init taking into account the base GSI of each IO APIC. - Use the vioapic base_gsi field in the PVH Dom0 build in order to populate the MADT IO APIC entries. I think this is a good canditate to be included in 4.9, it's a bugfix, and it's only used by PVH Dom0, so the risk is low IMHO. --- xen/arch/x86/hvm/dom0_build.c | 2 +- xen/arch/x86/hvm/vioapic.c | 45 +++++++++++++++++---------------------- xen/include/asm-x86/hvm/vioapic.h | 1 + 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c index db9be87612..020c355faf 100644 --- a/xen/arch/x86/hvm/dom0_build.c +++ b/xen/arch/x86/hvm/dom0_build.c @@ -719,7 +719,7 @@ static int __init pvh_setup_acpi_madt(struct domain *d, paddr_t *addr) io_apic->header.length = sizeof(*io_apic); io_apic->id = domain_vioapic(d, i)->id; io_apic->address = domain_vioapic(d, i)->base_address; - io_apic->global_irq_base = io_apic_gsi_base(i); + io_apic->global_irq_base = domain_vioapic(d, i)->base_gsi; io_apic++; } diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 5157db7a4e..c511fa7db6 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -64,37 +64,23 @@ static struct hvm_vioapic *addr_vioapic(const struct domain *d, struct hvm_vioapic *gsi_vioapic(const struct domain *d, unsigned int gsi, unsigned int *pin) { - unsigned int i, base_gsi = 0; + unsigned int i; for ( i = 0; i < d->arch.hvm_domain.nr_vioapics; i++ ) { struct hvm_vioapic *vioapic = domain_vioapic(d, i); - if ( gsi >= base_gsi && gsi < base_gsi + vioapic->nr_pins ) + if ( gsi >= vioapic->base_gsi && + gsi < vioapic->base_gsi + vioapic->nr_pins ) { - *pin = gsi - base_gsi; + *pin = gsi - vioapic->base_gsi; return vioapic; } - - base_gsi += vioapic->nr_pins; } return NULL; } -static unsigned int base_gsi(const struct domain *d, - const struct hvm_vioapic *vioapic) -{ - unsigned int nr_vioapics = d->arch.hvm_domain.nr_vioapics; - unsigned int base_gsi = 0, i = 0; - const struct hvm_vioapic *tmp; - - while ( i < nr_vioapics && (tmp = domain_vioapic(d, i++)) != vioapic ) - base_gsi += tmp->nr_pins; - - return base_gsi; -} - static uint32_t vioapic_read_indirect(const struct hvm_vioapic *vioapic) { uint32_t result = 0; @@ -180,7 +166,7 @@ static void vioapic_write_redirent( struct hvm_irq *hvm_irq = hvm_domain_irq(d); union vioapic_redir_entry *pent, ent; int unmasked = 0; - unsigned int gsi = base_gsi(d, vioapic) + idx; + unsigned int gsi = vioapic->base_gsi + idx; spin_lock(&d->arch.hvm_domain.irq_lock); @@ -340,7 +326,7 @@ static void vioapic_deliver(struct hvm_vioapic *vioapic, unsigned int pin) struct domain *d = vioapic_domain(vioapic); struct vlapic *target; struct vcpu *v; - unsigned int irq = base_gsi(d, vioapic) + pin; + unsigned int irq = vioapic->base_gsi + pin; ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock)); @@ -451,7 +437,7 @@ void vioapic_update_EOI(struct domain *d, u8 vector) { struct hvm_irq *hvm_irq = hvm_domain_irq(d); union vioapic_redir_entry *ent; - unsigned int i, base_gsi = 0; + unsigned int i; ASSERT(has_vioapic(d)); @@ -473,19 +459,18 @@ void vioapic_update_EOI(struct domain *d, u8 vector) if ( iommu_enabled ) { spin_unlock(&d->arch.hvm_domain.irq_lock); - hvm_dpci_eoi(d, base_gsi + pin, ent); + hvm_dpci_eoi(d, vioapic->base_gsi + pin, ent); spin_lock(&d->arch.hvm_domain.irq_lock); } if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) && !ent->fields.mask && - hvm_irq->gsi_assert_count[base_gsi + pin] ) + hvm_irq->gsi_assert_count[vioapic->base_gsi + pin] ) { ent->fields.remote_irr = 1; vioapic_deliver(vioapic, pin); } } - base_gsi += vioapic->nr_pins; } spin_unlock(&d->arch.hvm_domain.irq_lock); @@ -554,6 +539,7 @@ void vioapic_reset(struct domain *d) { vioapic->base_address = mp_ioapics[i].mpc_apicaddr; vioapic->id = mp_ioapics[i].mpc_apicid; + vioapic->base_gsi = io_apic_gsi_base(i); } vioapic->nr_pins = nr_pins; vioapic->domain = d; @@ -590,6 +576,8 @@ int vioapic_init(struct domain *d) { unsigned int nr_pins = is_hardware_domain(d) ? nr_ioapic_entries[i] : ARRAY_SIZE(domain_vioapic(d, 0)->domU.redirtbl); + unsigned int base_gsi = is_hardware_domain(d) ? io_apic_gsi_base(i) + : 0; if ( (domain_vioapic(d, i) = xmalloc_bytes(hvm_vioapic_size(nr_pins))) == NULL ) @@ -598,10 +586,15 @@ int vioapic_init(struct domain *d) return -ENOMEM; } domain_vioapic(d, i)->nr_pins = nr_pins; - nr_gsis += nr_pins; + nr_gsis = max(nr_gsis, base_gsi + nr_pins); } - ASSERT(hvm_domain_irq(d)->nr_gsis == nr_gsis); + /* + * NB: hvm_domain_irq(d)->nr_gsis is actually the highest GSI + 1, but + * there might be holes in this range (ie: GSIs that don't belong to any + * vIO APIC). + */ + ASSERT(hvm_domain_irq(d)->nr_gsis >= nr_gsis); d->arch.hvm_domain.nr_vioapics = nr_vioapics; vioapic_reset(d); diff --git a/xen/include/asm-x86/hvm/vioapic.h b/xen/include/asm-x86/hvm/vioapic.h index 8ec91d2bd1..2ceb60eaef 100644 --- a/xen/include/asm-x86/hvm/vioapic.h +++ b/xen/include/asm-x86/hvm/vioapic.h @@ -50,6 +50,7 @@ struct hvm_vioapic { struct domain *domain; uint32_t nr_pins; + unsigned int base_gsi; union { XEN_HVM_VIOAPIC(,); struct hvm_hw_vioapic domU;