From patchwork Tue Jul 4 13:49:18 2023 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: 13301285 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2F56CEB64D9 for ; Tue, 4 Jul 2023 13:50:19 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qGgPS-0002wM-U8; Tue, 04 Jul 2023 09:49:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qGgPQ-0002v4-TT; Tue, 04 Jul 2023 09:49:36 -0400 Received: from mail.ozlabs.org ([2404:9400:2221:ea00::3] helo=gandalf.ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qGgPO-0006Vm-Ma; Tue, 04 Jul 2023 09:49:36 -0400 Received: from gandalf.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4QwPKj4dCQz4wxn; Tue, 4 Jul 2023 23:49:29 +1000 (AEST) Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 4QwPKg5FWsz4wZw; Tue, 4 Jul 2023 23:49:27 +1000 (AEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: qemu-devel@nongnu.org Cc: qemu-ppc@nongnu.org, =?utf-8?b?RnLDqWTDqXJpYyBCYXJyYXQ=?= , Nicholas Piggin , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 1/4] ppc/xive: introduce a new XiveRouter end_notify() handler Date: Tue, 4 Jul 2023 15:49:18 +0200 Message-ID: <20230704134921.2626692-2-clg@kaod.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230704134921.2626692-1-clg@kaod.org> References: <20230704134921.2626692-1-clg@kaod.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2404:9400:2221:ea00::3; envelope-from=SRS0=18er=CW=kaod.org=clg@ozlabs.org; helo=gandalf.ozlabs.org X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org It will help us model the END triggers on the PowerNV machine, which can be rerouted from another interrupt controller. Signed-off-by: Cédric Le Goater --- include/hw/ppc/xive.h | 2 ++ hw/intc/xive.c | 28 ++++++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index 9f580a2699e9..f120874e0ff1 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -401,6 +401,7 @@ struct XiveRouterClass { int (*write_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt, uint8_t word_number); uint8_t (*get_block_id)(XiveRouter *xrtr); + void (*end_notify)(XiveRouter *xrtr, XiveEAS *eas); }; int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, uint32_t eas_idx, @@ -414,6 +415,7 @@ int xive_router_get_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt, uint8_t word_number); void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked); +void xive_router_end_notify(XiveRouter *xrtr, XiveEAS *eas); /* * XIVE Presenter diff --git a/hw/intc/xive.c b/hw/intc/xive.c index f60c8783455f..e36e695a691b 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1518,6 +1518,13 @@ static void xive_router_realize(DeviceState *dev, Error **errp) assert(xrtr->xfb); } +static void xive_router_end_notify_handler(XiveRouter *xrtr, XiveEAS *eas) +{ + XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr); + + return xrc->end_notify(xrtr, eas); +} + /* * Encode the HW CAM line in the block group mode format : * @@ -1664,8 +1671,7 @@ static bool xive_router_end_es_notify(XiveRouter *xrtr, uint8_t end_blk, * another chip. We don't model the PowerBus but the END trigger * message has the same parameters than in the function below. */ -static void xive_router_end_notify(XiveRouter *xrtr, uint8_t end_blk, - uint32_t end_idx, uint32_t end_data) +void xive_router_end_notify(XiveRouter *xrtr, XiveEAS *eas) { XiveEND end; uint8_t priority; @@ -1675,6 +1681,10 @@ static void xive_router_end_notify(XiveRouter *xrtr, uint8_t end_blk, XiveNVT nvt; bool found; + uint8_t end_blk = xive_get_field64(EAS_END_BLOCK, eas->w); + uint32_t end_idx = xive_get_field64(EAS_END_INDEX, eas->w); + uint32_t end_data = xive_get_field64(EAS_END_DATA, eas->w); + /* END cache lookup */ if (xive_router_get_end(xrtr, end_blk, end_idx, &end)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No END %x/%x\n", end_blk, @@ -1817,10 +1827,7 @@ do_escalation: /* * The END trigger becomes an Escalation trigger */ - xive_router_end_notify(xrtr, - xive_get_field32(END_W4_ESC_END_BLOCK, end.w4), - xive_get_field32(END_W4_ESC_END_INDEX, end.w4), - xive_get_field32(END_W5_ESC_END_DATA, end.w5)); + xive_router_end_notify_handler(xrtr, (XiveEAS *) &end.w4); } void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked) @@ -1871,10 +1878,7 @@ void xive_router_notify(XiveNotifier *xn, uint32_t lisn, bool pq_checked) /* * The event trigger becomes an END trigger */ - xive_router_end_notify(xrtr, - xive_get_field64(EAS_END_BLOCK, eas.w), - xive_get_field64(EAS_END_INDEX, eas.w), - xive_get_field64(EAS_END_DATA, eas.w)); + xive_router_end_notify_handler(xrtr, &eas); } static Property xive_router_properties[] = { @@ -1887,12 +1891,16 @@ static void xive_router_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass); + XiveRouterClass *xrc = XIVE_ROUTER_CLASS(klass); dc->desc = "XIVE Router Engine"; device_class_set_props(dc, xive_router_properties); /* Parent is SysBusDeviceClass. No need to call its realize hook */ dc->realize = xive_router_realize; xnc->notify = xive_router_notify; + + /* By default, the router handles END triggers locally */ + xrc->end_notify = xive_router_end_notify; } static const TypeInfo xive_router_info = { From patchwork Tue Jul 4 13:49:19 2023 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: 13301286 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 46818EB64D9 for ; Tue, 4 Jul 2023 13:50:38 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qGgPR-0002vJ-BO; Tue, 04 Jul 2023 09:49:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qGgPQ-0002uk-FO; Tue, 04 Jul 2023 09:49:36 -0400 Received: from gandalf.ozlabs.org ([150.107.74.76]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qGgPO-0006WS-Eq; Tue, 04 Jul 2023 09:49:36 -0400 Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4QwPKm0nsHz4wxp; Tue, 4 Jul 2023 23:49:32 +1000 (AEST) Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 4QwPKk1PQcz4wZw; Tue, 4 Jul 2023 23:49:29 +1000 (AEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: qemu-devel@nongnu.org Cc: qemu-ppc@nongnu.org, =?utf-8?b?RnLDqWTDqXJpYyBCYXJyYXQ=?= , Nicholas Piggin , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 2/4] ppc/pnv: handle END triggers between chips with MMIOs Date: Tue, 4 Jul 2023 15:49:19 +0200 Message-ID: <20230704134921.2626692-3-clg@kaod.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230704134921.2626692-1-clg@kaod.org> References: <20230704134921.2626692-1-clg@kaod.org> MIME-Version: 1.0 Received-SPF: pass client-ip=150.107.74.76; envelope-from=SRS0=18er=CW=kaod.org=clg@ozlabs.org; helo=gandalf.ozlabs.org X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.25, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The notify page of the interrupt controller can either be used to receive trigger events from the HW controllers (PHB, PSI) or to reroute interrupts between Interrupt Controller. In which case, the VSD table is used to determine the address of the notify page of the remote IC and the store data is forwarded. Today, our model grabs the remote VSD (EAS, END, NVT) address using pnv_xive_get_remote() helper but this is incorrect. EAS accesses should always be local and END triggers should be rerouted using a store on the remote IC notify page. We still have a shortcut in the model for the NVT accesses. It will be addressed later when we model the PC mmio operations. Signed-off-by: Cédric Le Goater --- hw/intc/pnv_xive_regs.h | 1 + hw/intc/pnv_xive.c | 68 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/hw/intc/pnv_xive_regs.h b/hw/intc/pnv_xive_regs.h index c78f030c0260..793847638bce 100644 --- a/hw/intc/pnv_xive_regs.h +++ b/hw/intc/pnv_xive_regs.h @@ -228,6 +228,7 @@ * VSD and is only meant to be used in indirect mode ! */ #define VSD_MODE PPC_BITMASK(0, 1) +#define VSD_MODE_INVALID 0 #define VSD_MODE_SHARED 1 #define VSD_MODE_EXCLUSIVE 2 #define VSD_MODE_FORWARD 3 diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index e536b3ec26e5..b41ab85e01bd 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -225,6 +225,11 @@ static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t type, uint8_t blk, /* Remote VST access */ if (GETFIELD(VSD_MODE, vsd) == VSD_MODE_FORWARD) { + if (type != VST_TSEL_VPDT) { + xive_error(xive, "VST: invalid access on remote VST %s %x/%x !?", + info->name, blk, idx); + return 0; + } xive = pnv_xive_get_remote(blk); return xive ? pnv_xive_vst_addr(xive, type, blk, idx) : 0; @@ -275,12 +280,26 @@ static int pnv_xive_vst_write(PnvXive *xive, uint32_t type, uint8_t blk, static int pnv_xive_get_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx, XiveEND *end) { + PnvXive *xive = PNV_XIVE(xrtr); + + if (pnv_xive_block_id(xive) != blk) { + xive_error(xive, "VST: END %x/%x is remote !?", blk, idx); + return -1; + } + return pnv_xive_vst_read(PNV_XIVE(xrtr), VST_TSEL_EQDT, blk, idx, end); } static int pnv_xive_write_end(XiveRouter *xrtr, uint8_t blk, uint32_t idx, XiveEND *end, uint8_t word_number) { + PnvXive *xive = PNV_XIVE(xrtr); + + if (pnv_xive_block_id(xive) != blk) { + xive_error(xive, "VST: END %x/%x is remote !?", blk, idx); + return -1; + } + return pnv_xive_vst_write(PNV_XIVE(xrtr), VST_TSEL_EQDT, blk, idx, end, word_number); } @@ -1349,6 +1368,50 @@ static const MemoryRegionOps pnv_xive_ic_reg_ops = { #define PNV_XIVE_SYNC_PUSH 0xf00 /* Sync push context */ #define PNV_XIVE_SYNC_VPC 0xf80 /* Sync remove VPC store */ +static void pnv_xive_end_notify(XiveRouter *xrtr, XiveEAS *eas) +{ + PnvXive *xive = PNV_XIVE(xrtr); + uint8_t end_blk = xive_get_field64(EAS_END_BLOCK, eas->w); + uint32_t end_idx = xive_get_field64(EAS_END_INDEX, eas->w); + uint32_t end_data = xive_get_field64(EAS_END_DATA, eas->w); + uint64_t end_vsd = xive->vsds[VST_TSEL_EQDT][end_blk]; + + switch (GETFIELD(VSD_MODE, end_vsd)) { + case VSD_MODE_EXCLUSIVE: + /* Perform the END notification on the local IC. */ + xive_router_end_notify(xrtr, eas); + break; + + case VSD_MODE_FORWARD: { + MemTxResult result; + uint64_t notif_port = end_vsd & VSD_ADDRESS_MASK; + uint64_t data = XIVE_TRIGGER_END | XIVE_TRIGGER_PQ | + be64_to_cpu(eas->w); + + /* Forward the store on the remote IC notify page. */ + address_space_stq_be(&address_space_memory, notif_port, data, + MEMTXATTRS_UNSPECIFIED, &result); + if (result != MEMTX_OK) { + xive_error(xive, "IC: Forward notif END %x/%x [%x] failed @%" + HWADDR_PRIx, end_blk, end_idx, end_data, notif_port); + return; + } + break; + } + + case VSD_MODE_INVALID: + default: + /* Set FIR */ + xive_error(xive, "IC: Invalid END VSD for block %x", end_blk); + return; + } +} + +/* + * The notify page can either be used to receive trigger events from + * the HW controllers (PHB, PSI) or to reroute interrupts between + * Interrupt controllers. + */ static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val) { uint8_t blk; @@ -1357,8 +1420,8 @@ static void pnv_xive_ic_hw_trigger(PnvXive *xive, hwaddr addr, uint64_t val) trace_pnv_xive_ic_hw_trigger(addr, val); if (val & XIVE_TRIGGER_END) { - xive_error(xive, "IC: END trigger at @0x%"HWADDR_PRIx" data 0x%"PRIx64, - addr, val); + val = cpu_to_be64(val); + pnv_xive_end_notify(XIVE_ROUTER(xive), (XiveEAS *) &val); return; } @@ -1998,6 +2061,7 @@ static void pnv_xive_class_init(ObjectClass *klass, void *data) xrc->get_nvt = pnv_xive_get_nvt; xrc->write_nvt = pnv_xive_write_nvt; xrc->get_block_id = pnv_xive_get_block_id; + xrc->end_notify = pnv_xive_end_notify; xnc->notify = pnv_xive_notify; xpc->match_nvt = pnv_xive_match_nvt; From patchwork Tue Jul 4 13:49:20 2023 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: 13301287 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2E7B0EB64D9 for ; Tue, 4 Jul 2023 13:51:00 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qGgPV-0002xK-1M; Tue, 04 Jul 2023 09:49:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qGgPT-0002we-E9; Tue, 04 Jul 2023 09:49:39 -0400 Received: from gandalf.ozlabs.org ([150.107.74.76]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qGgPR-0006X5-D1; Tue, 04 Jul 2023 09:49:39 -0400 Received: from gandalf.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4QwPKp42pjz4wxq; Tue, 4 Jul 2023 23:49:34 +1000 (AEST) Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 4QwPKm4fhwz4wZw; Tue, 4 Jul 2023 23:49:32 +1000 (AEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: qemu-devel@nongnu.org Cc: qemu-ppc@nongnu.org, =?utf-8?b?RnLDqWTDqXJpYyBCYXJyYXQ=?= , Nicholas Piggin , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 3/4] ppc/pnv: add support for the PC MMIOs Date: Tue, 4 Jul 2023 15:49:20 +0200 Message-ID: <20230704134921.2626692-4-clg@kaod.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230704134921.2626692-1-clg@kaod.org> References: <20230704134921.2626692-1-clg@kaod.org> MIME-Version: 1.0 Received-SPF: pass client-ip=150.107.74.76; envelope-from=SRS0=18er=CW=kaod.org=clg@ozlabs.org; helo=gandalf.ozlabs.org X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.25, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Associated with each NVT is a CI page address that is intended for use by privileged interrupt management code to adjust the backlog counts of a logical server and interrupt pending buffer for a specific virtual processor. This backlog count adjustment function is valuable to avoid extraneous physical interrupts when the hardware accumulates the backlog count per event queue post while the software handles multiple event queue entries on a single physical interrupt. Likewise adjusting the Interrupt Pending Buffer allows a virtual processor to process event queues of other priorities during one physical interrupt cycle. The NVT adjustment is initiated by a store byte (stb) or a double word load instruction. For the store byte operations that increment/decrement a backlog count the value of the data byte is the amount added (counter saturates at maximum value) / subtracted from the backlog counter (the counter does not go negative). For the store byte operations that set/reset an IPB priority bit, the data byte is ignored. The load double word operations that target a backlog counter increment/decrement the backlog count by one count (counter saturates at maximum value / does not go negative). Load operations to an IPB return the pre-operation value, while load operations to a backlog counter return the post-operation value, in both cases right justified in the double word. Programs may use the load operations if they need to know when the operation has completed; this may be accomplished by introducing a data dependency upon the returned load data. Other operation lengths (other than store byte and load double word) are not supported – results are boundedly undefined. Signed-off-by: Cédric Le Goater --- hw/intc/pnv_xive.c | 85 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index b41ab85e01bd..844965cfe281 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -1773,17 +1773,92 @@ static uint64_t pnv_xive_pc_read(void *opaque, hwaddr addr, unsigned size) { PnvXive *xive = PNV_XIVE(opaque); + uint32_t offset = (addr & 0x1F0) >> 4; + uint8_t nvt_blk; + uint32_t nvt_idx; + XiveNVT nvt; + uint8_t ipb; + uint64_t ret = -1; - xive_error(xive, "PC: invalid read @%"HWADDR_PRIx, addr); - return -1; + if (size != 8) { + xive_error(xive, "PC: invalid read size %d @%"HWADDR_PRIx"\n", + size, addr); + return -1; + } + + /* TODO: support multi block */ + nvt_blk = pnv_xive_block_id(xive); + nvt_idx = addr >> TM_SHIFT; + + if (xive_router_get_nvt(XIVE_ROUTER(xive), nvt_blk, nvt_idx, &nvt)) { + xive_error(xive, "PC: invalid NVT %x/%x\n", nvt_blk, nvt_idx); + return -1; + } + + ipb = xive_get_field32(NVT_W4_IPB, nvt.w4); + + switch (offset) { + case 0x0 ... 0x7: /* set IBP bit x */ + ret = ipb; + ipb |= 1 << offset; + break; + case 0x10 ... 0x17: /* reset IBP bit x */ + ret = ipb; + ipb &= ~(1 << (offset - 0x10)); + break; + + case 0x8 ... 0xF: /* TODO: increment backlog */ + /* backlog = offset - 0x8; */ + case 0x18 ... 0x1F: /* TODO: decrement backlog */ + /* backlog = offset - 0x18; */ + default: + xive_error(xive, "PC: invalid write @%"HWADDR_PRIx"\n", addr); + } + + if (ipb != xive_get_field32(NVT_W4_IPB, nvt.w4)) { + nvt.w4 = xive_set_field32(NVT_W4_IPB, nvt.w4, ipb); + xive_router_write_nvt(XIVE_ROUTER(xive), nvt_blk, nvt_idx, &nvt, 4); + } + + return ret; } static void pnv_xive_pc_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { PnvXive *xive = PNV_XIVE(opaque); + uint32_t offset = (addr & 0x1F0) >> 4; + uint8_t nvt_blk; + uint32_t nvt_idx; + XiveNVT nvt; + + if (size != 1) { + xive_error(xive, "PC: invalid write size %d @%"HWADDR_PRIx"\n", + size, addr); + return; + } + + /* TODO: support multi block */ + nvt_blk = pnv_xive_block_id(xive); + nvt_idx = addr >> TM_SHIFT; + + if (xive_router_get_nvt(XIVE_ROUTER(xive), nvt_blk, nvt_idx, &nvt)) { + xive_error(xive, "PC: invalid NVT %x/%x\n", nvt_blk, nvt_idx); + return; + } - xive_error(xive, "PC: invalid write to VC @%"HWADDR_PRIx, addr); + switch (offset) { + case 0x0 ... 0x7: /* ignored */ + case 0x10 ... 0x17: /* ignored */ + break; + + case 0x8 ... 0xF: /* TODO: Add to backlog */ + /* backlog = offset - 0x8; */ + case 0x18 ... 0x1F: /* TODO: substract to backlog */ + /* backlog = offset - 0x18; */ + default: + xive_error(xive, "PC: invalid write @%"HWADDR_PRIx"\n", addr); + } } static const MemoryRegionOps pnv_xive_pc_ops = { @@ -1791,11 +1866,11 @@ static const MemoryRegionOps pnv_xive_pc_ops = { .write = pnv_xive_pc_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; From patchwork Tue Jul 4 13:49:21 2023 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: 13301288 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8C1F5EB64DA for ; Tue, 4 Jul 2023 13:51:04 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qGgPX-00032E-Mi; Tue, 04 Jul 2023 09:49:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qGgPV-0002yn-TS; Tue, 04 Jul 2023 09:49:41 -0400 Received: from mail.ozlabs.org ([2404:9400:2221:ea00::3] helo=gandalf.ozlabs.org) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qGgPT-0006XV-Kl; Tue, 04 Jul 2023 09:49:41 -0400 Received: from gandalf.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4QwPKs0B3Sz4wZp; Tue, 4 Jul 2023 23:49:37 +1000 (AEST) Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 4QwPKq0p4sz4wZw; Tue, 4 Jul 2023 23:49:34 +1000 (AEST) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: qemu-devel@nongnu.org Cc: qemu-ppc@nongnu.org, =?utf-8?b?RnLDqWTDqXJpYyBCYXJyYXQ=?= , Nicholas Piggin , =?utf-8?q?C=C3=A9dric_Le_Goater?= Subject: [RFC PATCH 4/4] ppc/pnv: Add support for degenerative interrupts (POWER LSI) Date: Tue, 4 Jul 2023 15:49:21 +0200 Message-ID: <20230704134921.2626692-5-clg@kaod.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230704134921.2626692-1-clg@kaod.org> References: <20230704134921.2626692-1-clg@kaod.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2404:9400:2221:ea00::3; envelope-from=SRS0=18er=CW=kaod.org=clg@ozlabs.org; helo=gandalf.ozlabs.org X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.25, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org POWER systems have a degenerative interrupt path used during system bring up. It doesn't rely on the XIVE routing logic and all thread 0 of each core are notified. TODO: Need a new OS driver to check modeling. Signed-off-by: Cédric Le Goater --- include/hw/ppc/pnv_xive.h | 15 ++++++ include/hw/ppc/xive.h | 1 + hw/intc/pnv_xive.c | 109 +++++++++++++++++++++++++------------- hw/intc/xive.c | 22 ++++++++ 4 files changed, 111 insertions(+), 36 deletions(-) diff --git a/include/hw/ppc/pnv_xive.h b/include/hw/ppc/pnv_xive.h index 9c48430ee418..0ab3a8651ec1 100644 --- a/include/hw/ppc/pnv_xive.h +++ b/include/hw/ppc/pnv_xive.h @@ -15,6 +15,17 @@ #include "qom/object.h" #include "hw/ppc/xive2.h" +struct PnvXive; + +#define TYPE_PNV_XIVE_LSI "pnv-xive-lsi" +#define PNV_XIVE_LSI(obj) OBJECT_CHECK(PnvXiveLsi, (obj), TYPE_PNV_XIVE_LSI) + +typedef struct PnvXiveLsi { + DeviceState parent_obj; + + struct PnvXive *xive; +} PnvXiveLsi; + #define TYPE_PNV_XIVE "pnv-xive" OBJECT_DECLARE_TYPE(PnvXive, PnvXiveClass, PNV_XIVE) @@ -71,6 +82,10 @@ struct PnvXive { XiveSource ipi_source; XiveENDSource end_source; + /* Lsi handlers */ + PnvXiveLsi lsi_xive; + XiveSource lsi_source; + /* Interrupt controller registers */ uint64_t regs[0x300]; diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index f120874e0ff1..983a475dd77c 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -534,6 +534,7 @@ void xive_tctx_reset(XiveTCTX *tctx); void xive_tctx_destroy(XiveTCTX *tctx); void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb); void xive_tctx_reset_os_signal(XiveTCTX *tctx); +void xive_tctx_lsi_notify(XiveTCTX *tctx); /* * KVM XIVE device helpers diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index 844965cfe281..9bf138cdea2c 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -991,7 +991,7 @@ static void pnv_xive_ic_reg_write(void *opaque, hwaddr offset, memory_region_del_subregion(&xive->ic_mmio, &xive->ic_notify_mmio); memory_region_del_subregion(&xive->ic_mmio, - &xive->ic_lsi_mmio); + &xive->lsi_source.esb_mmio); memory_region_del_subregion(&xive->ic_mmio, &xive->tm_indirect_mmio); @@ -1010,7 +1010,7 @@ static void pnv_xive_ic_reg_write(void *opaque, hwaddr offset, &xive->ic_notify_mmio); memory_region_add_subregion(&xive->ic_mmio, 2ul << xive->ic_shift, - &xive->ic_lsi_mmio); + &xive->lsi_source.esb_mmio); memory_region_add_subregion(&xive->ic_mmio, 4ull << xive->ic_shift, &xive->tm_indirect_mmio); @@ -1503,39 +1503,9 @@ static const MemoryRegionOps pnv_xive_ic_notify_ops = { }; /* - * IC - LSI MMIO handlers (not modeled) + * IC - LSI MMIO handlers */ -static void pnv_xive_ic_lsi_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PnvXive *xive = PNV_XIVE(opaque); - - xive_error(xive, "IC: LSI invalid write @%"HWADDR_PRIx, addr); -} - -static uint64_t pnv_xive_ic_lsi_read(void *opaque, hwaddr addr, unsigned size) -{ - PnvXive *xive = PNV_XIVE(opaque); - - xive_error(xive, "IC: LSI invalid read @%"HWADDR_PRIx, addr); - return -1; -} - -static const MemoryRegionOps pnv_xive_ic_lsi_ops = { - .read = pnv_xive_ic_lsi_read, - .write = pnv_xive_ic_lsi_write, - .endianness = DEVICE_BIG_ENDIAN, - .valid = { - .min_access_size = 8, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 8, - .max_access_size = 8, - }, -}; - /* * IC - Indirect TIMA MMIO handlers */ @@ -1975,6 +1945,10 @@ static void pnv_xive_init(Object *obj) TYPE_XIVE_SOURCE); object_initialize_child(obj, "end_source", &xive->end_source, TYPE_XIVE_END_SOURCE); + object_initialize_child(obj, "lsi_source", &xive->lsi_source, + TYPE_XIVE_SOURCE); + object_initialize_child(obj, "xive_lsi", &xive->lsi_xive, + TYPE_PNV_XIVE_LSI); } /* @@ -1988,6 +1962,7 @@ static void pnv_xive_realize(DeviceState *dev, Error **errp) PnvXive *xive = PNV_XIVE(dev); PnvXiveClass *pxc = PNV_XIVE_GET_CLASS(dev); XiveSource *xsrc = &xive->ipi_source; + XiveSource *lsi_xsrc = &xive->lsi_source; XiveENDSource *end_xsrc = &xive->end_source; Error *local_err = NULL; @@ -2037,9 +2012,20 @@ static void pnv_xive_realize(DeviceState *dev, Error **errp) &pnv_xive_ic_notify_ops, xive, "xive-ic-notify", 1 << xive->ic_shift); - /* The Pervasive LSI trigger and EOI pages (not modeled) */ - memory_region_init_io(&xive->ic_lsi_mmio, OBJECT(dev), &pnv_xive_ic_lsi_ops, - xive, "xive-ic-lsi", 2 << xive->ic_shift); + /* The Pervasive LSI trigger and EOI pages */ + + object_property_set_link(OBJECT(&xive->lsi_xive), "xive", OBJECT(xive), + &error_abort); + if (!qdev_realize(DEVICE(&xive->lsi_xive), NULL, errp)) { + return; + } + + object_property_set_int(OBJECT(lsi_xsrc), "nr-irqs", 1, &error_fatal); + object_property_set_link(OBJECT(lsi_xsrc), "xive", OBJECT(&xive->lsi_xive), + &error_abort); + if (!qdev_realize(DEVICE(lsi_xsrc), NULL, &local_err)) { + return; + } /* Thread Interrupt Management Area (Indirect) */ memory_region_init_io(&xive->tm_indirect_mmio, OBJECT(dev), @@ -2156,9 +2142,60 @@ static const TypeInfo pnv_xive_info = { } }; +/* + * Notifier proxy for LSI sources + * + * Trigger all threads 0 + */ +static void pnv_xive_lsi_notify(XiveNotifier *xn, uint32_t srcno, + bool pq_checked) +{ + PnvXive *xive = PNV_XIVE_LSI(xn)->xive; + PnvChip *chip = xive->chip; + int i; + + for (i = 0; i < chip->nr_cores; i++) { + PowerPCCPU *cpu = chip->cores[i]->threads[0]; + + if (!pnv_xive_is_cpu_enabled(xive, cpu)) { + continue; + } + + xive_tctx_lsi_notify(XIVE_TCTX(pnv_cpu_state(cpu)->intc)); + } +} + +static Property pnv_xive_lsi_properties[] = { + DEFINE_PROP_LINK("xive", PnvXiveLsi, xive, TYPE_PNV_XIVE, PnvXive *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void pnv_xive_lsi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass); + + dc->desc = "PowerNV XIVE LSI proxy"; + device_class_set_props(dc, pnv_xive_lsi_properties); + + xnc->notify = pnv_xive_lsi_notify; +}; + +static const TypeInfo pnv_xive_lsi_info = { + .name = TYPE_PNV_XIVE_LSI, + .parent = TYPE_DEVICE, + .instance_size = sizeof(PnvXiveLsi), + .class_init = pnv_xive_lsi_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_XIVE_NOTIFIER }, + { } + } +}; + static void pnv_xive_register_types(void) { type_register_static(&pnv_xive_info); + type_register_static(&pnv_xive_lsi_info); } type_init(pnv_xive_register_types) diff --git a/hw/intc/xive.c b/hw/intc/xive.c index e36e695a691b..d81b7d6ea6b4 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -90,6 +90,8 @@ static uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring) regs[TM_CPPR], regs[TM_NSR]); } + /* TODO: drop LP bit when LE is set */ + return (nsr << 8) | regs[TM_CPPR]; } @@ -153,6 +155,26 @@ void xive_tctx_ipb_update(XiveTCTX *tctx, uint8_t ring, uint8_t ipb) xive_tctx_notify(tctx, ring); } +void xive_tctx_lsi_notify(XiveTCTX *tctx) +{ + uint32_t qw3w2 = xive_tctx_word2(&tctx->regs[TM_QW3_HV_PHYS]); + uint8_t *regs = &tctx->regs[TM_QW3_HV_PHYS]; + + /* + * If the HW context (VT) is enabled and the LSI enabled (LE) bit + * is set, raise the LSI pending bit and notify the CPU on the HV + * line. + */ + if ((be32_to_cpu(qw3w2) & (TM_QW3W2_VT | TM_QW3W2_LE)) == + (TM_QW3W2_VT | TM_QW3W2_LE)) { + qw3w2 = xive_set_field32(TM_QW3W2_LP, qw3w2, 1); + memcpy(&tctx->regs[TM_QW3_HV_PHYS + TM_WORD2], &qw3w2, 4); + + regs[TM_NSR] |= (TM_QW3_NSR_HE_LSI << 6); + qemu_irq_raise(xive_tctx_output(tctx, TM_QW3_HV_PHYS)); + } +} + /* * XIVE Thread Interrupt Management Area (TIMA) */