From nobody Sat Nov 1 07:50:17 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 152666214448885.10584406326666; Fri, 18 May 2018 09:49:04 -0700 (PDT) Received: from localhost ([::1]:39979 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fJiYx-0007RF-Q9 for importer@patchew.org; Fri, 18 May 2018 12:49:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56691) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fJiUa-0004hs-Hk for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fJiUX-0008A0-8k for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:32 -0400 Received: from 6.mo178.mail-out.ovh.net ([46.105.53.132]:55573) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fJiUX-0007xG-1Z for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:29 -0400 Received: from player774.ha.ovh.net (unknown [10.109.122.53]) by mo178.mail-out.ovh.net (Postfix) with ESMTP id 2E69315445 for ; Fri, 18 May 2018 18:44:21 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player774.ha.ovh.net (Postfix) with ESMTPSA id DB47240090; Fri, 18 May 2018 18:44:14 +0200 (CEST) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= To: qemu-ppc@nongnu.org Date: Fri, 18 May 2018 18:44:02 +0200 Message-Id: <20180518164405.11804-2-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180518164405.11804-1-clg@kaod.org> References: <20180518164405.11804-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 208572959498799955 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedthedrfeefgddutddvucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 46.105.53.132 Subject: [Qemu-devel] [PATCH 1/4] spapr: remove irq_hint parameter from spapr_irq_alloc() 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: Alexey Kardashevskiy , Greg Kurz , qemu-devel@nongnu.org, =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This IRQ number hint can possibly be used by the VIO devices if the "irq" property is defined on the command line but it seems it is never the case. It is not used in libvirt for instance. So, let's remove it to simplify future changes. Nevertheless, this is a compatibbility breakage that will be addressed by the subsequent patches which introduce IRQ number allocator handlers per machine version. Signed-off-by: C=C3=A9dric Le Goater --- include/hw/ppc/spapr.h | 3 +-- hw/ppc/spapr.c | 21 ++++++--------------- hw/ppc/spapr_events.c | 7 +++---- hw/ppc/spapr_vio.c | 2 +- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index d60b7c6d7a8b..2cfdfdd67eaf 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -773,8 +773,7 @@ int spapr_get_vcpu_id(PowerPCCPU *cpu); void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp); PowerPCCPU *spapr_find_cpu(int vcpu_id); =20 -int spapr_irq_alloc(sPAPRMachineState *spapr, int irq_hint, bool lsi, - Error **errp); +int spapr_irq_alloc(sPAPRMachineState *spapr, bool lsi, Error **errp); int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi, bool align, Error **errp); void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 32ab3c43b6c0..05a924a5f2da 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3798,28 +3798,19 @@ static void spapr_irq_set_lsi(sPAPRMachineState *sp= apr, int irq, bool lsi) ics_set_irq_type(spapr->ics, irq - spapr->ics->offset, lsi); } =20 -int spapr_irq_alloc(sPAPRMachineState *spapr, int irq_hint, bool lsi, - Error **errp) +int spapr_irq_alloc(sPAPRMachineState *spapr, bool lsi, Error **errp) { ICSState *ics =3D spapr->ics; int irq; =20 assert(ics); =20 - if (irq_hint) { - if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) { - error_setg(errp, "can't allocate IRQ %d: already in use", irq_= hint); - return -1; - } - irq =3D irq_hint; - } else { - irq =3D ics_find_free_block(ics, 1, 1); - if (irq < 0) { - error_setg(errp, "can't allocate IRQ: no IRQ left"); - return -1; - } - irq +=3D ics->offset; + irq =3D ics_find_free_block(ics, 1, 1); + if (irq < 0) { + error_setg(errp, "can't allocate IRQ: no IRQ left"); + return -1; } + irq +=3D ics->offset; =20 spapr_irq_set_lsi(spapr, irq, lsi); trace_spapr_irq_alloc(irq); diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 86836f0626dc..64a67439beac 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -712,8 +712,7 @@ void spapr_events_init(sPAPRMachineState *spapr) spapr->event_sources =3D spapr_event_sources_new(); =20 spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_EPOW, - spapr_irq_alloc(spapr, 0, false, - &error_fatal)); + spapr_irq_alloc(spapr, false, &error_fata= l)); =20 /* NOTE: if machine supports modern/dedicated hotplug event source, * we add it to the device-tree unconditionally. This means we may @@ -725,8 +724,8 @@ void spapr_events_init(sPAPRMachineState *spapr) */ if (spapr->use_hotplug_event_source) { spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_HOT= _PLUG, - spapr_irq_alloc(spapr, 0, false, - &error_fatal)); + spapr_irq_alloc(spapr, false, + &error_fatal)); } =20 spapr->epow_notifier.notify =3D spapr_powerdown_req; diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 472dd6f33a96..cc064f64fccf 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -455,7 +455,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev,= Error **errp) dev->qdev.id =3D id; } =20 - dev->irq =3D spapr_irq_alloc(spapr, dev->irq, false, &local_err); + dev->irq =3D spapr_irq_alloc(spapr, false, &local_err); if (local_err) { error_propagate(errp, local_err); return; --=20 2.13.6 From nobody Sat Nov 1 07:50:17 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1526661984515347.38618581770004; Fri, 18 May 2018 09:46:24 -0700 (PDT) Received: from localhost ([::1]:39967 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fJiWN-0005iM-Jw for importer@patchew.org; Fri, 18 May 2018 12:46:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56686) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fJiUa-0004hm-BM for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fJiUX-00089u-8W for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:32 -0400 Received: from 3.mo177.mail-out.ovh.net ([46.105.36.172]:50481) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fJiUX-000896-1v for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:29 -0400 Received: from player774.ha.ovh.net (unknown [10.109.120.8]) by mo177.mail-out.ovh.net (Postfix) with ESMTP id 57D21B1648 for ; Fri, 18 May 2018 18:44:27 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player774.ha.ovh.net (Postfix) with ESMTPSA id 0E92640095; Fri, 18 May 2018 18:44:21 +0200 (CEST) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= To: qemu-ppc@nongnu.org Date: Fri, 18 May 2018 18:44:03 +0200 Message-Id: <20180518164405.11804-3-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180518164405.11804-1-clg@kaod.org> References: <20180518164405.11804-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 210261810002627411 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedthedrfeefgddutddvucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 46.105.36.172 Subject: [Qemu-devel] [PATCH 2/4] sparp_pci: simplify how the PCI LSIs are allocated 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: Alexey Kardashevskiy , Greg Kurz , qemu-devel@nongnu.org, =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" PCI LSIs are today allocated one by one using the IRQ alloc_block routine. Change the code sequence to first allocate a PCI_NUM_PINS block. It will help us providing a generic IRQ framework to the machine. Signed-off-by: C=C3=A9dric Le Goater Reviewed-by: Greg Kurz --- hw/ppc/spapr_pci.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 39a14980d397..4fd97ffe4c6e 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1546,6 +1546,8 @@ static void spapr_phb_realize(DeviceState *dev, Error= **errp) sPAPRTCETable *tcet; const unsigned windows_supported =3D sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; + uint32_t irq; + Error *local_err =3D NULL; =20 if (!spapr) { error_setg(errp, TYPE_SPAPR_PCI_HOST_BRIDGE " needs a pseries mach= ine"); @@ -1694,18 +1696,15 @@ static void spapr_phb_realize(DeviceState *dev, Err= or **errp) QLIST_INSERT_HEAD(&spapr->phbs, sphb, list); =20 /* Initialize the LSI table */ - for (i =3D 0; i < PCI_NUM_PINS; i++) { - uint32_t irq; - Error *local_err =3D NULL; - - irq =3D spapr_irq_alloc_block(spapr, 1, true, false, &local_err); - if (local_err) { - error_propagate(errp, local_err); - error_prepend(errp, "can't allocate LSIs: "); - return; - } + irq =3D spapr_irq_alloc_block(spapr, PCI_NUM_PINS, true, false, &local= _err); + if (local_err) { + error_propagate(errp, local_err); + error_prepend(errp, "can't allocate LSIs: "); + return; + } =20 - sphb->lsi_table[i].irq =3D irq; + for (i =3D 0; i < PCI_NUM_PINS; i++) { + sphb->lsi_table[i].irq =3D irq + i; } =20 /* allocate connectors for child PCI devices */ --=20 2.13.6 From nobody Sat Nov 1 07:50:17 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1526662303435477.0614998692283; Fri, 18 May 2018 09:51:43 -0700 (PDT) Received: from localhost ([::1]:39995 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fJibW-0002cK-EO for importer@patchew.org; Fri, 18 May 2018 12:51:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56740) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fJiUg-0004kk-LB for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fJiUd-0008Jj-DI for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:38 -0400 Received: from 4.mo69.mail-out.ovh.net ([46.105.42.102]:39156) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fJiUd-0008H2-2o for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:35 -0400 Received: from player774.ha.ovh.net (unknown [10.109.120.34]) by mo69.mail-out.ovh.net (Postfix) with ESMTP id 79DB1163A8 for ; Fri, 18 May 2018 18:44:33 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player774.ha.ovh.net (Postfix) with ESMTPSA id 3598540080; Fri, 18 May 2018 18:44:27 +0200 (CEST) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= To: qemu-ppc@nongnu.org Date: Fri, 18 May 2018 18:44:04 +0200 Message-Id: <20180518164405.11804-4-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180518164405.11804-1-clg@kaod.org> References: <20180518164405.11804-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 211950660410182483 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedthedrfeefgddutddvucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 46.105.42.102 Subject: [Qemu-devel] [PATCH 3/4] spapr: introduce a generic IRQ frontend to 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: Alexey Kardashevskiy , Greg Kurz , qemu-devel@nongnu.org, =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This proposal moves all the related IRQ routines of the sPAPR machine behind a class interface to prepare for future changes in the IRQ controller model. First of which is a reorganization of the IRQ number space layout and a second, coming later, will be to integrate the support for the new POWER9 XIVE IRQ controller. The new interface defines a set of fixed IRQ number ranges, for each IRQ type, in which devices allocate the IRQ numbers they need depending on a unique device index. Here is the layout : SPAPR_IRQ_IPI 0x0 /* 1 IRQ per CPU */ SPAPR_IRQ_EPOW 0x1000 /* 1 IRQ per device */ SPAPR_IRQ_HOTPLUG 0x1001 /* 1 IRQ per device */ SPAPR_IRQ_VIO 0x1100 /* 1 IRQ per device */ SPAPR_IRQ_PCI_LSI 0x1200 /* 4 IRQs per device */ SPAPR_IRQ_PCI_MSI 0x1400 /* 1K IRQs per device */ The IPI range is reserved for future use when XIVE support comes in. The routines of this interface encompass the previous needs and the new ones and seem complex but the provided IRQ backend should implement what we have today without any functional changes. Each device model is modified to take the new interface into account using the IRQ range/type definitions and a device index. A part from the VIO devices, lacking an id, the changes are relatively simple. Signed-off-by: C=C3=A9dric Le Goater Reviewed-by: Greg Kurz --- include/hw/ppc/spapr.h | 10 +- include/hw/ppc/spapr_irq.h | 46 +++++++++ hw/ppc/spapr.c | 177 +--------------------------------- hw/ppc/spapr_events.c | 7 +- hw/ppc/spapr_irq.c | 233 +++++++++++++++++++++++++++++++++++++++++= ++++ hw/ppc/spapr_pci.c | 21 +++- hw/ppc/spapr_vio.c | 5 +- hw/ppc/Makefile.objs | 2 +- 8 files changed, 308 insertions(+), 193 deletions(-) create mode 100644 include/hw/ppc/spapr_irq.h create mode 100644 hw/ppc/spapr_irq.c diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 2cfdfdd67eaf..4eb212b16a51 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -3,10 +3,10 @@ =20 #include "sysemu/dma.h" #include "hw/boards.h" -#include "hw/ppc/xics.h" #include "hw/ppc/spapr_drc.h" #include "hw/mem/pc-dimm.h" #include "hw/ppc/spapr_ovec.h" +#include "hw/ppc/spapr_irq.h" =20 struct VIOsPAPRBus; struct sPAPRPHBState; @@ -104,6 +104,7 @@ struct sPAPRMachineClass { unsigned n_dma, uint32_t *liobns, Error **errp); sPAPRResizeHPT resize_hpt_default; sPAPRCapabilities default_caps; + sPAPRIrq *irq; }; =20 /** @@ -773,13 +774,6 @@ int spapr_get_vcpu_id(PowerPCCPU *cpu); void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp); PowerPCCPU *spapr_find_cpu(int vcpu_id); =20 -int spapr_irq_alloc(sPAPRMachineState *spapr, bool lsi, Error **errp); -int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi, - bool align, Error **errp); -void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num); -qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq); - - int spapr_caps_pre_load(void *opaque); int spapr_caps_pre_save(void *opaque); =20 diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h new file mode 100644 index 000000000000..caf4c33d4cec --- /dev/null +++ b/include/hw/ppc/spapr_irq.h @@ -0,0 +1,46 @@ +/* + * QEMU PowerPC sPAPR IRQ backend definitions + * + * Copyright (c) 2018, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ +#ifndef HW_SPAPR_IRQ_H +#define HW_SPAPR_IRQ_H + +#include "hw/ppc/xics.h" + +/* + * IRQ ranges + */ +#define SPAPR_IRQ_IPI 0x0 /* 1 IRQ per CPU */ +#define SPAPR_IRQ_EPOW 0x1000 /* 1 IRQ per device */ +#define SPAPR_IRQ_HOTPLUG 0x1001 /* 1 IRQ per device */ +#define SPAPR_IRQ_VIO 0x1100 /* 1 IRQ per device */ +#define SPAPR_IRQ_PCI_LSI 0x1200 /* 4 IRQs per device */ +#define SPAPR_IRQ_PCI_MSI 0x1400 /* 1K IRQs per device covered by + * a bitmap allocator */ + +typedef struct sPAPRIrq { + uint32_t nr_irqs; + + void (*init)(sPAPRMachineState *spapr, Error **errp); + int (*alloc)(sPAPRMachineState *spapr, uint32_t range, uint32_t index, + Error **errp); + int (*alloc_block)(sPAPRMachineState *spapr, uint32_t range, + uint32_t index, int num, bool align, Error **errp); + void (*free)(sPAPRMachineState *spapr, int irq, int num, Error **errp); + qemu_irq (*qirq)(sPAPRMachineState *spapr, int irq); +} sPAPRIrq; + +extern sPAPRIrq spapr_irq_default; + +int spapr_irq_alloc(sPAPRMachineState *spapr, uint32_t range, uint32_t ind= ex, + Error **errp); +int spapr_irq_alloc_block(sPAPRMachineState *spapr, uint32_t range, + uint32_t index, int num, bool align, Error **err= p); +void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num, Error **er= rp); +qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq); + +#endif /* HW_SPAPR_IRQ_H */ diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 05a924a5f2da..09f095d73eae 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -116,33 +116,6 @@ static bool spapr_is_thread0_in_vcore(sPAPRMachineStat= e *spapr, return spapr_get_vcpu_id(cpu) % spapr->vsmt =3D=3D 0; } =20 -static ICSState *spapr_ics_create(sPAPRMachineState *spapr, - const char *type_ics, - int nr_irqs, Error **errp) -{ - Error *local_err =3D NULL; - Object *obj; - - obj =3D object_new(type_ics); - object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort); - object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr), - &error_abort); - object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err); - if (local_err) { - goto error; - } - object_property_set_bool(obj, true, "realized", &local_err); - if (local_err) { - goto error; - } - - return ICS_SIMPLE(obj); - -error: - error_propagate(errp, local_err); - return NULL; -} - static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque) { /* Dummy entries correspond to unused ICPState objects in older QEMUs, @@ -183,32 +156,6 @@ static int xics_max_server_number(sPAPRMachineState *s= papr) return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads); } =20 -static void xics_system_init(MachineState *machine, int nr_irqs, Error **e= rrp) -{ - sPAPRMachineState *spapr =3D SPAPR_MACHINE(machine); - - if (kvm_enabled()) { - if (machine_kernel_irqchip_allowed(machine) && - !xics_kvm_init(spapr, errp)) { - spapr->icp_type =3D TYPE_KVM_ICP; - spapr->ics =3D spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs, = errp); - } - if (machine_kernel_irqchip_required(machine) && !spapr->ics) { - error_prepend(errp, "kernel_irqchip requested but unavailable:= "); - return; - } - } - - if (!spapr->ics) { - xics_spapr_init(spapr); - spapr->icp_type =3D TYPE_ICP; - spapr->ics =3D spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs, e= rrp); - if (!spapr->ics) { - return; - } - } -} - static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, int smt_threads) { @@ -2580,7 +2527,7 @@ static void spapr_machine_init(MachineState *machine) load_limit =3D MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; =20 /* Set up Interrupt Controller before we create the VCPUs */ - xics_system_init(machine, XICS_IRQS_SPAPR, &error_fatal); + smc->irq->init(spapr, &error_fatal); =20 /* Set up containers for ibm,client-architecture-support negotiated op= tions */ @@ -3766,127 +3713,6 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int = vcpu_id) return cpu ? ICP(cpu->intc) : NULL; } =20 -#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 =3D 0; first < ics->nr_irqs; first +=3D alignnum) { - if (num > (ics->nr_irqs - first)) { - return -1; - } - for (i =3D first; i < first + num; ++i) { - if (!ICS_IRQ_FREE(ics, i)) { - break; - } - } - if (i =3D=3D (first + num)) { - return first; - } - } - - return -1; -} - -/* - * Allocate the IRQ number and set the IRQ type, LSI or MSI - */ -static void spapr_irq_set_lsi(sPAPRMachineState *spapr, int irq, bool lsi) -{ - ics_set_irq_type(spapr->ics, irq - spapr->ics->offset, lsi); -} - -int spapr_irq_alloc(sPAPRMachineState *spapr, bool lsi, Error **errp) -{ - ICSState *ics =3D spapr->ics; - int irq; - - assert(ics); - - irq =3D ics_find_free_block(ics, 1, 1); - if (irq < 0) { - error_setg(errp, "can't allocate IRQ: no IRQ left"); - return -1; - } - irq +=3D ics->offset; - - spapr_irq_set_lsi(spapr, irq, lsi); - trace_spapr_irq_alloc(irq); - - return irq; -} - -/* - * Allocate block of consecutive IRQs, and return the number of the first = IRQ in - * the block. If align=3D=3Dtrue, aligns the first IRQ number to num. - */ -int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi, - bool align, Error **errp) -{ - ICSState *ics =3D spapr->ics; - int i, first =3D -1; - - assert(ics); - - /* - * MSIMesage::data is used for storing VIRQ so - * it has to be aligned to num to support multiple - * MSI vectors. MSI-X is not affected by this. - * The hint is used for the first IRQ, the rest should - * be allocated continuously. - */ - if (align) { - assert((num =3D=3D 1) || (num =3D=3D 2) || (num =3D=3D 4) || - (num =3D=3D 8) || (num =3D=3D 16) || (num =3D=3D 32)); - first =3D ics_find_free_block(ics, num, num); - } else { - first =3D ics_find_free_block(ics, num, 1); - } - if (first < 0) { - error_setg(errp, "can't find a free %d-IRQ block", num); - return -1; - } - - first +=3D ics->offset; - for (i =3D first; i < first + num; ++i) { - spapr_irq_set_lsi(spapr, i, lsi); - } - - trace_spapr_irq_alloc_block(first, num, lsi, align); - - return first; -} - -void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num) -{ - ICSState *ics =3D spapr->ics; - int srcno =3D irq - ics->offset; - int i; - - if (ics_valid_irq(ics, irq)) { - trace_spapr_irq_free(0, irq, num); - for (i =3D 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)); - } - } -} - -qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq) -{ - ICSState *ics =3D spapr->ics; - - if (ics_valid_irq(ics, irq)) { - return ics->qirqs[irq - ics->offset]; - } - - return NULL; -} - static void spapr_pic_print_info(InterruptStatsProvider *obj, Monitor *mon) { @@ -4007,6 +3833,7 @@ static void spapr_machine_class_init(ObjectClass *oc,= void *data) smc->default_caps.caps[SPAPR_CAP_SBBC] =3D SPAPR_CAP_BROKEN; smc->default_caps.caps[SPAPR_CAP_IBS] =3D SPAPR_CAP_BROKEN; spapr_caps_add_properties(smc, &error_abort); + smc->irq =3D &spapr_irq_default; } =20 static const TypeInfo spapr_machine_info =3D { diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 64a67439beac..e457c5f18189 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -712,7 +712,8 @@ void spapr_events_init(sPAPRMachineState *spapr) spapr->event_sources =3D spapr_event_sources_new(); =20 spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_EPOW, - spapr_irq_alloc(spapr, false, &error_fata= l)); + spapr_irq_alloc(spapr, SPAPR_IRQ_EPOW, 0, + &error_fatal)); =20 /* NOTE: if machine supports modern/dedicated hotplug event source, * we add it to the device-tree unconditionally. This means we may @@ -724,8 +725,8 @@ void spapr_events_init(sPAPRMachineState *spapr) */ if (spapr->use_hotplug_event_source) { spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_HOT= _PLUG, - spapr_irq_alloc(spapr, false, - &error_fatal)); + spapr_irq_alloc(spapr, SPAPR_IRQ_HOTP= LUG, + 0, &error_fatal)); } =20 spapr->epow_notifier.notify =3D spapr_powerdown_req; diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c new file mode 100644 index 000000000000..ff6cb1aafd25 --- /dev/null +++ b/hw/ppc/spapr_irq.c @@ -0,0 +1,233 @@ +/* + * QEMU PowerPC sPAPR IRQ backend + * + * Copyright (c) 2018, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/pci/pci.h" +#include "hw/ppc/spapr.h" +#include "sysemu/kvm.h" +#include "trace.h" + +/* + * Legacy XICS IRQ backend. + * + * The device IRQ 'range' is used to identify LSIs, and the device + * 'index' is unused + */ +static ICSState *spapr_ics_create(sPAPRMachineState *spapr, + const char *type_ics, + int nr_irqs, Error **errp) +{ + Error *local_err =3D NULL; + Object *obj; + + obj =3D object_new(type_ics); + object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort); + object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr), + &error_abort); + object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err); + if (local_err) { + goto error; + } + object_property_set_bool(obj, true, "realized", &local_err); + if (local_err) { + goto error; + } + + return ICS_SIMPLE(obj); + +error: + error_propagate(errp, local_err); + return NULL; +} + +static void spapr_irq_init_2_12(sPAPRMachineState *spapr, Error **errp) +{ + MachineState *machine =3D MACHINE(spapr); + sPAPRMachineClass *smc =3D SPAPR_MACHINE_GET_CLASS(machine); + uint32_t nr_irqs =3D smc->irq->nr_irqs; + + if (kvm_enabled()) { + if (machine_kernel_irqchip_allowed(machine) && + !xics_kvm_init(spapr, errp)) { + spapr->icp_type =3D TYPE_KVM_ICP; + spapr->ics =3D spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs, = errp); + } + if (machine_kernel_irqchip_required(machine) && !spapr->ics) { + error_prepend(errp, "kernel_irqchip requested but unavailable:= "); + return; + } + } + + if (!spapr->ics) { + xics_spapr_init(spapr); + spapr->icp_type =3D TYPE_ICP; + spapr->ics =3D spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs, e= rrp); + if (!spapr->ics) { + return; + } + } +} + +#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 =3D 0; first < ics->nr_irqs; first +=3D alignnum) { + if (num > (ics->nr_irqs - first)) { + return -1; + } + for (i =3D first; i < first + num; ++i) { + if (!ICS_IRQ_FREE(ics, i)) { + break; + } + } + if (i =3D=3D (first + num)) { + return first; + } + } + + return -1; +} + +static int spapr_irq_alloc_2_12(sPAPRMachineState *spapr, + uint32_t range, uint32_t index, Error **er= rp) +{ + ICSState *ics =3D spapr->ics; + bool lsi =3D (range =3D=3D SPAPR_IRQ_PCI_LSI); + int srcno; + + assert(ics); + + srcno =3D ics_find_free_block(ics, 1, 1); + if (srcno < 0) { + error_setg(errp, "can't allocate IRQ: no IRQ left"); + return -1; + } + + ics_set_irq_type(ics, srcno, lsi); + trace_spapr_irq_alloc(srcno); + + return ics->offset + srcno; +} + +/* + * Allocate block of consecutive IRQs, and return the number of the first = IRQ in + * the block. If align=3D=3Dtrue, aligns the first IRQ number to num. + */ +static int spapr_irq_alloc_block_2_12(sPAPRMachineState *spapr, uint32_t r= ange, + uint32_t index, int num, bool align, + Error **errp) +{ + ICSState *ics =3D spapr->ics; + bool lsi =3D (range =3D=3D SPAPR_IRQ_PCI_LSI); + int i, srcno; + + assert(ics); + + /* + * MSIMessage::data is used for storing VIRQ so it has to be + * aligned to num to support multiple MSI vectors. MSI-X is not + * affected by this. + */ + if (align) { + assert((num =3D=3D 1) || (num =3D=3D 2) || (num =3D=3D 4) || + (num =3D=3D 8) || (num =3D=3D 16) || (num =3D=3D 32)); + srcno =3D ics_find_free_block(ics, num, num); + } else { + srcno =3D ics_find_free_block(ics, num, 1); + } + + if (srcno < 0) { + error_setg(errp, "can't find a free %d-IRQ block", num); + return -1; + } + + for (i =3D srcno; i < srcno + num; ++i) { + ics_set_irq_type(ics, i, lsi); + } + + trace_spapr_irq_alloc_block(srcno, num, lsi, align); + + return ics->offset + srcno; +} + +static void spapr_irq_free_2_12(sPAPRMachineState *spapr, int irq, int num, + Error **errp) +{ + ICSState *ics =3D spapr->ics; + uint32_t srcno =3D irq - ics->offset; + int i; + + if (ics_valid_irq(ics, irq)) { + trace_spapr_irq_free(0, irq, num); + for (i =3D srcno; i < srcno + num; ++i) { + if (ICS_IRQ_FREE(ics, i)) { + trace_spapr_irq_free_warn(0, i); + } + memset(&ics->irqs[i], 0, sizeof(ICSIRQState)); + } + } +} + +static qemu_irq spapr_qirq_2_12(sPAPRMachineState *spapr, int irq) +{ + ICSState *ics =3D spapr->ics; + uint32_t srcno =3D irq - ics->offset; + + if (ics_valid_irq(ics, irq)) { + return ics->qirqs[srcno]; + } + + return NULL; +} + +sPAPRIrq spapr_irq_default =3D { + .nr_irqs =3D XICS_IRQS_SPAPR, + .init =3D spapr_irq_init_2_12, + .alloc =3D spapr_irq_alloc_2_12, + .alloc_block =3D spapr_irq_alloc_block_2_12, + .free =3D spapr_irq_free_2_12, + .qirq =3D spapr_qirq_2_12, +}; + +int spapr_irq_alloc(sPAPRMachineState *spapr, uint32_t range, uint32_t ind= ex, + Error **errp) +{ + sPAPRMachineClass *smc =3D SPAPR_MACHINE_GET_CLASS(spapr); + + return smc->irq->alloc(spapr, range, index, errp); +} + +int spapr_irq_alloc_block(sPAPRMachineState *spapr, uint32_t range, + uint32_t index, int num, bool align, Error **err= p) +{ + sPAPRMachineClass *smc =3D SPAPR_MACHINE_GET_CLASS(spapr); + + return smc->irq->alloc_block(spapr, range, index, num, align, errp); +} + +void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num, + Error **errp) +{ + sPAPRMachineClass *smc =3D SPAPR_MACHINE_GET_CLASS(spapr); + + smc->irq->free(spapr, irq, num, errp); +} + +qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq) +{ + sPAPRMachineClass *smc =3D SPAPR_MACHINE_GET_CLASS(spapr); + + return smc->irq->qirq(spapr, irq); +} diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 4fd97ffe4c6e..cca4169fa10b 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -333,7 +333,12 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPR= MachineState *spapr, return; } =20 - spapr_irq_free(spapr, msi->first_irq, msi->num); + spapr_irq_free(spapr, msi->first_irq, msi->num, &err); + if (err) { + error_reportf_err(err, "Can't remove MSIs for device %x: ", + config_addr); + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); + } if (msi_present(pdev)) { spapr_msi_setmsg(pdev, 0, false, 0, 0); } @@ -371,8 +376,8 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRM= achineState *spapr, } =20 /* Allocate MSIs */ - irq =3D spapr_irq_alloc_block(spapr, req_num, false, - ret_intr_type =3D=3D RTAS_TYPE_MSI, &err); + irq =3D spapr_irq_alloc_block(spapr, SPAPR_IRQ_PCI_MSI, phb->index, re= q_num, + ret_intr_type =3D=3D RTAS_TYPE_MSI, &err); if (err) { error_reportf_err(err, "Can't allocate MSIs for device %x: ", config_addr); @@ -382,7 +387,11 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPR= MachineState *spapr, =20 /* Release previous MSIs */ if (msi) { - spapr_irq_free(spapr, msi->first_irq, msi->num); + spapr_irq_free(spapr, msi->first_irq, msi->num, &err); + if (err) { + error_reportf_err(err, "Can't remove MSIs for device %x: ", + config_addr); + } g_hash_table_remove(phb->msi, &config_addr); } =20 @@ -1696,7 +1705,8 @@ static void spapr_phb_realize(DeviceState *dev, Error= **errp) QLIST_INSERT_HEAD(&spapr->phbs, sphb, list); =20 /* Initialize the LSI table */ - irq =3D spapr_irq_alloc_block(spapr, PCI_NUM_PINS, true, false, &local= _err); + irq =3D spapr_irq_alloc_block(spapr, SPAPR_IRQ_PCI_LSI, sphb->index, + PCI_NUM_PINS, false, &local_err); if (local_err) { error_propagate(errp, local_err); error_prepend(errp, "can't allocate LSIs: "); @@ -2112,6 +2122,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, _FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges)); _FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg))); _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1)); + /* TODO: fix the total count of allocatable MSIs per PHB */ _FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS_SPA= PR)); =20 /* Dynamic DMA window */ diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index cc064f64fccf..7ec69a29d806 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -416,6 +416,9 @@ static void spapr_vio_busdev_reset(DeviceState *qdev) } } =20 +/* TODO : poor VIO device indexing ... */ +static uint32_t vio_index; + static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp) { sPAPRMachineState *spapr =3D SPAPR_MACHINE(qdev_get_machine()); @@ -455,7 +458,7 @@ static void spapr_vio_busdev_realize(DeviceState *qdev,= Error **errp) dev->qdev.id =3D id; } =20 - dev->irq =3D spapr_irq_alloc(spapr, false, &local_err); + dev->irq =3D spapr_irq_alloc(spapr, SPAPR_IRQ_VIO, vio_index++, &local= _err); if (local_err) { error_propagate(errp, local_err); return; diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index 86d82a6ec3ac..4fe3b7804d43 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -4,7 +4,7 @@ obj-y +=3D ppc.o ppc_booke.o fdt.o obj-$(CONFIG_PSERIES) +=3D spapr.o spapr_caps.o spapr_vio.o spapr_events.o obj-$(CONFIG_PSERIES) +=3D spapr_hcall.o spapr_iommu.o spapr_rtas.o obj-$(CONFIG_PSERIES) +=3D spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o -obj-$(CONFIG_PSERIES) +=3D spapr_cpu_core.o spapr_ovec.o +obj-$(CONFIG_PSERIES) +=3D spapr_cpu_core.o spapr_ovec.o spapr_irq.o # IBM PowerNV obj-$(CONFIG_POWERNV) +=3D pnv.o pnv_xscom.o pnv_core.o pnv_lpc.o pnv_psi.= o pnv_occ.o pnv_bmc.o ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy) --=20 2.13.6 From nobody Sat Nov 1 07:50:17 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 152666201994561.419730068662375; Fri, 18 May 2018 09:46:59 -0700 (PDT) Received: from localhost ([::1]:39968 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fJiWx-000645-3f for importer@patchew.org; Fri, 18 May 2018 12:46:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56778) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fJiUo-0004sg-SF for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fJiUl-0008RO-NP for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:46 -0400 Received: from 4.mo179.mail-out.ovh.net ([46.105.36.149]:53270) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fJiUl-0008PY-DK for qemu-devel@nongnu.org; Fri, 18 May 2018 12:44:43 -0400 Received: from player774.ha.ovh.net (unknown [10.109.122.111]) by mo179.mail-out.ovh.net (Postfix) with ESMTP id 8E4CCC3B71 for ; Fri, 18 May 2018 18:44:39 +0200 (CEST) Received: from zorba.kaod.org.com (LFbn-TOU-1-49-10.w86-201.abo.wanadoo.fr [86.201.141.10]) (Authenticated sender: clg@kaod.org) by player774.ha.ovh.net (Postfix) with ESMTPSA id 603914009B; Fri, 18 May 2018 18:44:33 +0200 (CEST) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= To: qemu-ppc@nongnu.org Date: Fri, 18 May 2018 18:44:05 +0200 Message-Id: <20180518164405.11804-5-clg@kaod.org> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180518164405.11804-1-clg@kaod.org> References: <20180518164405.11804-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 213639510090091347 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedthedrfeefgddutddvucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 46.105.36.149 Subject: [Qemu-devel] [PATCH 4/4] spapr: introduce a new IRQ backend using fixed IRQ number ranges 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: Alexey Kardashevskiy , Greg Kurz , qemu-devel@nongnu.org, =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= , David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The proposed layout of the IRQ number space is organized as follow : RANGES DEVICES 0x0000 - 0x0FFF Reserved for future use (IPI =3D 2) 0x1000 - 0x1000 1 EPOW 0x1001 - 0x1001 1 HOTPLUG 0x1002 - 0x10FF unused 0x1100 - 0x11FF 256 VIO devices (1 IRQ each) 0x1200 - 0x1283 32 PCI LSI devices (4 IRQs each) 0x1284 - 0x13FF unused 0x1400 - 0x17FF PCI MSI device 1 (1024 IRQs each) 0x1800 - 0x1BFF PCI MSI device 1 0x1c00 - 0x1FFF PCI MSI device 2 0x2000 .... not allocated. Need to increase NR_IRQS The MSI range is a bit more complex to handle as the IRQS are dynamically allocated by the guest OS. In consequence, we use a bitmap allocator under the machine for these. The XICS IRQ number space is increased to 4K, which gives three MSI ranges of 1K for the PHBs. The XICS source IRQ numbers still have the 4K offset. Signed-off-by: C=C3=A9dric Le Goater --- include/hw/ppc/spapr.h | 2 + include/hw/ppc/spapr_irq.h | 12 +++ hw/ppc/spapr.c | 22 +++++ hw/ppc/spapr_irq.c | 220 +++++++++++++++++++++++++++++++++++++++++= +++- 4 files changed, 255 insertions(+), 1 deletion(-) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 4eb212b16a51..fcc1b1c1451d 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -165,6 +165,8 @@ struct sPAPRMachineState { char *kvm_type; MemoryHotplugState hotplug_memory; =20 + int32_t nr_irqs; + unsigned long *irq_map; const char *icp_type; =20 bool cmd_line_caps[SPAPR_CAP_NUM]; diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index caf4c33d4cec..d1af4c4d11ba 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -22,8 +22,16 @@ #define SPAPR_IRQ_PCI_MSI 0x1400 /* 1K IRQs per device covered by * a bitmap allocator */ =20 +typedef struct sPAPRPIrqRange { + const char *name; + uint32_t offset; + uint32_t width; + uint32_t max_index; +} sPAPRPIrqRange; + typedef struct sPAPRIrq { uint32_t nr_irqs; + const sPAPRPIrqRange *ranges; =20 void (*init)(sPAPRMachineState *spapr, Error **errp); int (*alloc)(sPAPRMachineState *spapr, uint32_t range, uint32_t index, @@ -35,6 +43,10 @@ typedef struct sPAPRIrq { } sPAPRIrq; =20 extern sPAPRIrq spapr_irq_default; +extern sPAPRIrq spapr_irq_2_12; + +const sPAPRPIrqRange *spapr_irq_get_range(sPAPRMachineState *spapr, + uint32_t offset); =20 int spapr_irq_alloc(sPAPRMachineState *spapr, uint32_t range, uint32_t ind= ex, Error **errp); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 09f095d73eae..f2ebd6f20414 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1848,6 +1848,24 @@ static const VMStateDescription vmstate_spapr_patb_e= ntry =3D { }, }; =20 +static bool spapr_irq_map_needed(void *opaque) +{ + sPAPRMachineState *spapr =3D opaque; + + return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->nr_irqs); +} + +static const VMStateDescription vmstate_spapr_irq_map =3D { + .name =3D "spapr_irq_map", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D spapr_irq_map_needed, + .fields =3D (VMStateField[]) { + VMSTATE_BITMAP(irq_map, sPAPRMachineState, 0, nr_irqs), + VMSTATE_END_OF_LIST() + }, +}; + static const VMStateDescription vmstate_spapr =3D { .name =3D "spapr", .version_id =3D 3, @@ -1875,6 +1893,7 @@ static const VMStateDescription vmstate_spapr =3D { &vmstate_spapr_cap_cfpc, &vmstate_spapr_cap_sbbc, &vmstate_spapr_cap_ibs, + &vmstate_spapr_irq_map, NULL } }; @@ -3916,7 +3935,10 @@ static void spapr_machine_2_12_instance_options(Mach= ineState *machine) =20 static void spapr_machine_2_12_class_options(MachineClass *mc) { + sPAPRMachineClass *smc =3D SPAPR_MACHINE_CLASS(mc); + spapr_machine_2_13_class_options(mc); + smc->irq =3D &spapr_irq_2_12; SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_12); } =20 diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index ff6cb1aafd25..bfffb1467336 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -192,7 +192,7 @@ static qemu_irq spapr_qirq_2_12(sPAPRMachineState *spap= r, int irq) return NULL; } =20 -sPAPRIrq spapr_irq_default =3D { +sPAPRIrq spapr_irq_2_12 =3D { .nr_irqs =3D XICS_IRQS_SPAPR, .init =3D spapr_irq_init_2_12, .alloc =3D spapr_irq_alloc_2_12, @@ -201,6 +201,224 @@ sPAPRIrq spapr_irq_default =3D { .qirq =3D spapr_qirq_2_12, }; =20 +/* + * IRQ range helpers for new IRQ backends + */ +const sPAPRPIrqRange *spapr_irq_get_range(sPAPRMachineState *spapr, + uint32_t offset) +{ + sPAPRMachineClass *smc =3D SPAPR_MACHINE_GET_CLASS(spapr); + const sPAPRPIrqRange *range =3D smc->irq->ranges; + + if (range) { + while (range->name && range->offset !=3D offset) { + range++; + } + + if (!range->name) { + return NULL; + } + } + + return range; +} + +static int spapr_irq_get_base(sPAPRMachineState *spapr, uint32_t offset, + uint32_t index, Error **errp) +{ + const sPAPRPIrqRange *range =3D spapr_irq_get_range(spapr, offset); + + if (!range) { + error_setg(errp, "Invalid IRQ range %x", offset); + return -1; + } + + if (index > range->max_index) { + error_setg(errp, "Index %d too big for IRQ range %s", index, + range->name); + return -1; + } + + return range->offset + index * range->width; +} + +static int spapr_irq_range_alloc(sPAPRMachineState *spapr, + uint32_t range, uint32_t index, Error **e= rrp) +{ + return spapr_irq_get_base(spapr, range, index, errp); +} + +static int spapr_irq_range_alloc_msi(sPAPRMachineState *spapr, uint32_t ra= nge, + uint32_t index, int num, bool align, + Error **errp) +{ + int msi_base =3D spapr_irq_get_base(spapr, SPAPR_IRQ_PCI_MSI, index, e= rrp); + int irq; + + /* + * The 'align_mask' parameter of bitmap_find_next_zero_area() + * should be one less than a power of 2; 0 means no + * alignment. Adapt the 'align' value of the former allocator + * to fit the requirements of bitmap_find_next_zero_area() + */ + align -=3D 1; + + irq =3D bitmap_find_next_zero_area(spapr->irq_map, spapr->nr_irqs, + msi_base, num, align); + if (irq =3D=3D spapr->nr_irqs) { + error_setg(errp, "can't find a free MSI %d-IRQ block", num); + return -1; + } + + bitmap_set(spapr->irq_map, irq, num); + return irq; +} + +static void spapr_irq_range_free_msi(sPAPRMachineState *spapr, int irq, in= t num) +{ + bitmap_clear(spapr->irq_map, irq, num); +} + +/* + * New XICS IRQ backend + * + * using the IRQ ranges and device indexes + */ +static void spapr_irq_init_2_13(sPAPRMachineState *spapr, Error **errp) +{ + MachineState *machine =3D MACHINE(spapr); + sPAPRMachineClass *smc =3D SPAPR_MACHINE_GET_CLASS(machine); + + spapr_irq_init_2_12(spapr, errp); + + /* + * Initialize the MSI IRQ allocator. The full XICS IRQ number + * space is covered even though the bottow IRQ numbers below the + * XICS source number offset (4K) are unused and that only MSI IRQ + * numbers can be allocated. We does waste some bytes but it makes + * things easier. We will optimize later. + */ + spapr->nr_irqs =3D smc->irq->nr_irqs + spapr->ics->offset; + spapr->irq_map =3D bitmap_new(spapr->nr_irqs); +} + +static int spapr_irq_alloc_2_13(sPAPRMachineState *spapr, + uint32_t range, uint32_t index, Error **er= rp) +{ + ICSState *ics =3D spapr->ics; + bool lsi =3D (range =3D=3D SPAPR_IRQ_PCI_LSI); + int irq =3D spapr_irq_range_alloc(spapr, range, index, errp); + + if (irq < 0) { + return irq; + } + + /* Update the IRQState in the XICS source */ + ics_set_irq_type(ics, irq - ics->offset, lsi); + + return irq; +} + +static int spapr_irq_alloc_block_2_13(sPAPRMachineState *spapr, uint32_t r= ange, + uint32_t index, int num, bool align, + Error **errp) +{ + ICSState *ics =3D spapr->ics; + bool lsi =3D (range =3D=3D SPAPR_IRQ_PCI_LSI); + int irq; + int i; + + if (range =3D=3D SPAPR_IRQ_PCI_MSI) { + irq =3D spapr_irq_range_alloc_msi(spapr, range, index, num, align,= errp); + } else { + /* TODO: check IRQ range width vs. required block size */ + irq =3D spapr_irq_range_alloc(spapr, range, index, errp); + } + + if (irq < 0) { + return irq; + } + + /* Update the IRQState in the XICS source */ + for (i =3D irq; i < irq + num; ++i) { + ics_set_irq_type(ics, i - ics->offset, lsi); + } + + return irq; +} + +static void spapr_irq_free_2_13(sPAPRMachineState *spapr, int irq, int num, + Error **errp) +{ + ICSState *ics =3D spapr->ics; + int msi_base =3D spapr_irq_get_base(spapr, SPAPR_IRQ_PCI_MSI, 0, NULL); + int i; + + /* Any IRQ below MSI base should not be freed */ + if (irq < msi_base) { + error_setg(errp, "IRQs %x-%x can not be freed", irq, irq + num); + return; + } + + spapr_irq_range_free_msi(spapr, irq, num); + + /* Clear out the IRQState from the XICS source */ + for (i =3D irq; i < irq + num; ++i) { + if (ics_valid_irq(ics, i)) { + uint32_t srcno =3D i - ics->offset; + memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState)); + } + } +} + +static qemu_irq spapr_qirq_2_13(sPAPRMachineState *spapr, int irq) +{ + return spapr_qirq_2_12(spapr, irq); +} + +/* + * RANGES DEVICES + * + * 0x0000 - 0x0FFF Reserved (IPI =3D 2) + * + * 0x1000 - 0x1000 1 EPOW + * 0x1001 - 0x1001 1 HOTPLUG + * 0x1002 - 0x10FF unused + * 0x1100 - 0x11FF 256 VIO devices (1 IRQ each) + * 0x1200 - 0x1283 32 PCI LSI devices (4 IRQs each) + * 0x1284 - 0x13FF unused + * 0x1400 - 0x17FF PCI MSI device 1 (1024 IRQs each) + * 0x1800 - 0x1BFF PCI MSI device 1 + * 0x1c00 - 0x1FFF PCI MSI device 2 + * 0x2000 .... not allocated. Need to increase NR_IRQS + */ +static const sPAPRPIrqRange spapr_irq_ranges_2_13[] =3D { + /* "IPI" Not used */ + { "EPOW", SPAPR_IRQ_EPOW, 1, 0 }, + { "HOTPLUG", SPAPR_IRQ_HOTPLUG, 1, 0 }, + { "VIO", SPAPR_IRQ_VIO, 1, 0xFF }, + { "PCI LSI", SPAPR_IRQ_PCI_LSI, PCI_NUM_PINS, 0x1F }, + { "PCI MSI", SPAPR_IRQ_PCI_MSI, 0x400, 0x1F }, + { NULL, 0, 0, 0 }, +}; + +/* + * Increase the XICS IRQ number space to 4K. It gives us 3 possible + * MSI ranges for the PHBs. The XICS Source IRQ numbers still have the + * 4K offset. + */ +#define SPAPR_NR_IRQS_2_13 0x1000 + +sPAPRIrq spapr_irq_default =3D { + .nr_irqs =3D SPAPR_NR_IRQS_2_13, + .init =3D spapr_irq_init_2_13, + .ranges =3D spapr_irq_ranges_2_13, + .alloc =3D spapr_irq_alloc_2_13, + .alloc_block =3D spapr_irq_alloc_block_2_13, + .free =3D spapr_irq_free_2_13, + .qirq =3D spapr_qirq_2_13, +}; + int spapr_irq_alloc(sPAPRMachineState *spapr, uint32_t range, uint32_t ind= ex, Error **errp) { --=20 2.13.6