From patchwork Thu Nov 9 10:14:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 836353 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yXkd53TYmz9t5Q for ; Fri, 10 Nov 2017 00:33:13 +1100 (AEDT) Received: from localhost ([::1]:36919 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eCmxD-0002IF-EX for incoming@patchwork.ozlabs.org; Thu, 09 Nov 2017 08:33:11 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40496) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eCmtc-0008Kf-Dt for qemu-devel@nongnu.org; Thu, 09 Nov 2017 08:29:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eCmtY-0005Cw-Dm for qemu-devel@nongnu.org; Thu, 09 Nov 2017 08:29:28 -0500 Received: from 1.mo68.mail-out.ovh.net ([46.105.41.146]:40213) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eCmtY-0005CS-57 for qemu-devel@nongnu.org; Thu, 09 Nov 2017 08:29:24 -0500 Received: from player750.ha.ovh.net (b6.ovh.net [213.186.33.56]) by mo68.mail-out.ovh.net (Postfix) with ESMTP id 9979B9BDDF for ; Thu, 9 Nov 2017 14:29:22 +0100 (CET) Received: from zorba.kaod.org.com (LFbn-1-2231-173.w90-76.abo.wanadoo.fr [90.76.52.173]) (Authenticated sender: clg@kaod.org) by player750.ha.ovh.net (Postfix) with ESMTPSA id BFCDE181B07; Thu, 9 Nov 2017 11:15:15 +0100 (CET) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: qemu-ppc@nongnu.org, qemu-devel@nongnu.org, David Gibson , Greg Kurz , Benjamin Herrenschmidt Date: Thu, 9 Nov 2017 11:14:31 +0100 Message-Id: <20171109101439.390-5-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20171109101439.390-1-clg@kaod.org> References: <20171109101439.390-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 3078491822706953043 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedttddriedugdegiecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 46.105.41.146 Subject: [Qemu-devel] [PATCH for-2.12 v2 04/12] spapr: move current IRQ allocation under the machine X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?C=C3=A9dric_Le_Goater?= Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Use the new XICSFabric operations to handle the IRQ number allocation directly under the machine. These changes only move code and adapt it to take into account the new API which uses IRQ numbers. On PowerNV, only provide a basic irq_test() operation. For the moment, there is no need for more. Signed-off-by: Cédric Le Goater --- hw/intc/trace-events | 2 -- hw/intc/xics.c | 3 ++- hw/intc/xics_spapr.c | 57 +++++++++------------------------------------------- hw/ppc/pnv.c | 18 +++++++++++++++++ hw/ppc/spapr.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--- hw/ppc/trace-events | 2 ++ 6 files changed, 85 insertions(+), 53 deletions(-) diff --git a/hw/intc/trace-events b/hw/intc/trace-events index b86f242b0fcf..e34ecf7a16e5 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -65,8 +65,6 @@ xics_ics_simple_reject(int nr, int srcno) "reject irq 0x%x [src %d]" xics_ics_simple_eoi(int nr) "ics_eoi: irq 0x%x" xics_alloc(int irq) "irq %d" xics_alloc_block(int first, int num, bool lsi, int align) "first irq %d, %d irqs, lsi=%d, alignnum %d" -xics_ics_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs" -xics_ics_free_warn(int src, int irq) "Source#%d, irq %d is already free" # hw/intc/s390_flic_kvm.c flic_create_device(int err) "flic: create device failed %d" diff --git a/hw/intc/xics.c b/hw/intc/xics.c index cc9816e7f204..2c4899f278e2 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -53,6 +53,7 @@ void icp_pic_print_info(ICPState *icp, Monitor *mon) void ics_pic_print_info(ICSState *ics, Monitor *mon) { uint32_t i; + XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(ics->xics); monitor_printf(mon, "ICS %4x..%4x %p\n", ics->offset, ics->offset + ics->nr_irqs - 1, ics); @@ -64,7 +65,7 @@ void ics_pic_print_info(ICSState *ics, Monitor *mon) for (i = 0; i < ics->nr_irqs; i++) { ICSIRQState *irq = ics->irqs + i; - if (!(irq->flags & XICS_FLAGS_IRQ_MASK)) { + if (!xic->irq_test(ics->xics, i + ics->offset)) { continue; } monitor_printf(mon, " %4x %s %02x %02x\n", diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index e8c0a1b3e903..de9e65d35247 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -245,50 +245,26 @@ void xics_spapr_init(sPAPRMachineState *spapr) spapr_register_hypercall(H_IPOLL, h_ipoll); } -#define ICS_IRQ_FREE(ics, srcno) \ - (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK))) - -static int ics_find_free_block(ICSState *ics, int num, int alignnum) -{ - int first, i; - - for (first = 0; first < ics->nr_irqs; first += alignnum) { - if (num > (ics->nr_irqs - first)) { - return -1; - } - for (i = first; i < first + num; ++i) { - if (!ICS_IRQ_FREE(ics, i)) { - break; - } - } - if (i == (first + num)) { - return first; - } - } - - return -1; -} - int spapr_ics_alloc(ICSState *ics, int irq_hint, bool lsi, Error **errp) { int irq; + XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(ics->xics); if (!ics) { return -1; } if (irq_hint) { - if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) { + if (xic->irq_test(ics->xics, irq_hint)) { error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint); return -1; } irq = irq_hint; } else { - irq = ics_find_free_block(ics, 1, 1); + irq = xic->irq_alloc_block(ics->xics, 1, 1); if (irq < 0) { error_setg(errp, "can't allocate IRQ: no IRQ left"); return -1; } - irq += ics->offset; } ics_set_irq_type(ics, irq - ics->offset, lsi); @@ -305,6 +281,7 @@ int spapr_ics_alloc_block(ICSState *ics, int num, bool lsi, bool align, Error **errp) { int i, first = -1; + XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(ics->xics); if (!ics) { return -1; @@ -320,9 +297,9 @@ int spapr_ics_alloc_block(ICSState *ics, int num, bool lsi, if (align) { assert((num == 1) || (num == 2) || (num == 4) || (num == 8) || (num == 16) || (num == 32)); - first = ics_find_free_block(ics, num, num); + first = xic->irq_alloc_block(ics->xics, num, num); } else { - first = ics_find_free_block(ics, num, 1); + first = xic->irq_alloc_block(ics->xics, num, 1); } if (first < 0) { error_setg(errp, "can't find a free %d-IRQ block", num); @@ -330,33 +307,19 @@ int spapr_ics_alloc_block(ICSState *ics, int num, bool lsi, } for (i = first; i < first + num; ++i) { - ics_set_irq_type(ics, i, lsi); + ics_set_irq_type(ics, i - ics->offset, lsi); } - first += ics->offset; trace_xics_alloc_block(first, num, lsi, align); return first; } -static void ics_free(ICSState *ics, int srcno, int num) -{ - int i; - - for (i = srcno; i < srcno + num; ++i) { - if (ICS_IRQ_FREE(ics, i)) { - trace_xics_ics_free_warn(0, i + ics->offset); - } - memset(&ics->irqs[i], 0, sizeof(ICSIRQState)); - } -} - void spapr_ics_free(ICSState *ics, int irq, int num) { - if (ics_valid_irq(ics, irq)) { - trace_xics_ics_free(0, irq, num); - ics_free(ics, irq - ics->offset, num); - } + XICSFabricClass *xic = XICS_FABRIC_GET_CLASS(ics->xics); + + xic->irq_free_block(ics->xics, irq, num); } void spapr_dt_xics(int nr_servers, void *fdt, uint32_t phandle) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index c35c439d816b..8288940ef9d7 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1018,6 +1018,23 @@ static ICPState *pnv_icp_get(XICSFabric *xi, int pir) return cpu ? ICP(cpu->intc) : NULL; } +static bool pnv_irq_test(XICSFabric *xi, int irq) +{ + PnvMachineState *pnv = POWERNV_MACHINE(xi); + int i; + + /* We don't have a IRQ allocator for the PowerNV machine yet, so + * just check that the IRQ number is valid for the PSI source + */ + for (i = 0; i < pnv->num_chips; i++) { + ICSState *ics = &pnv->chips[i]->psi.ics; + if (ics_valid_irq(ics, irq)) { + return true; + } + } + return false; +} + static void pnv_pic_print_info(InterruptStatsProvider *obj, Monitor *mon) { @@ -1102,6 +1119,7 @@ static void powernv_machine_class_init(ObjectClass *oc, void *data) xic->icp_get = pnv_icp_get; xic->ics_get = pnv_ics_get; xic->ics_resend = pnv_ics_resend; + xic->irq_test = pnv_irq_test; ispc->print_info = pnv_pic_print_info; powernv_machine_class_props_init(oc); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 84d68f2fdbae..481bfb0277df 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3536,19 +3536,69 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id) return cpu ? ICP(cpu->intc) : NULL; } +#define ICS_IRQ_FREE(ics, srcno) \ + (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK))) + +static int ics_find_free_block(ICSState *ics, int num, int alignnum) +{ + int first, i; + + for (first = 0; first < ics->nr_irqs; first += alignnum) { + if (num > (ics->nr_irqs - first)) { + return -1; + } + for (i = first; i < first + num; ++i) { + if (!ICS_IRQ_FREE(ics, i)) { + break; + } + } + if (i == (first + num)) { + return first; + } + } + + return -1; +} + static bool spapr_irq_test(XICSFabric *xi, int irq) { - return false; + sPAPRMachineState *spapr = SPAPR_MACHINE(xi); + ICSState *ics = spapr->ics; + int srcno = irq - ics->offset; + + return ICS_IRQ_FREE(ics, srcno); } static int spapr_irq_alloc_block(XICSFabric *xi, int count, int align) { - return -1; + sPAPRMachineState *spapr = SPAPR_MACHINE(xi); + ICSState *ics = spapr->ics; + int srcno; + + srcno = ics_find_free_block(ics, count, align); + if (srcno == -1) { + return -1; + } + + return srcno + ics->offset; } static void spapr_irq_free_block(XICSFabric *xi, int irq, int num) { - ; + sPAPRMachineState *spapr = SPAPR_MACHINE(xi); + ICSState *ics = spapr->ics; + int srcno = irq - ics->offset; + int i; + + if (ics_valid_irq(ics, irq)) { + trace_spapr_irq_free(0, irq, num); + for (i = srcno; i < srcno + num; ++i) { + if (ICS_IRQ_FREE(ics, i)) { + trace_spapr_irq_free_warn(0, i + ics->offset); + } + memset(&ics->irqs[i], 0, sizeof(ICSIRQState)); + } + } } static void spapr_pic_print_info(InterruptStatsProvider *obj, diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 4a6a6490fa78..dc9ab4c4deb3 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -12,6 +12,8 @@ spapr_pci_msi_retry(unsigned config_addr, unsigned req_num, unsigned max_irqs) " # hw/ppc/spapr.c spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes" spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes" +spapr_irq_free(int src, int irq, int num) "Source#%d, first irq %d, %d irqs" +spapr_irq_free_warn(int src, int irq) "Source#%d, irq %d is already free" # hw/ppc/spapr_hcall.c spapr_cas_pvr_try(uint32_t pvr) "0x%x"