From patchwork Mon Feb 5 14:19:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545614 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 D8367C48295 for ; Mon, 5 Feb 2024 14:20:46 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzpc-0003k3-O6; Mon, 05 Feb 2024 09:20:20 -0500 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 1rWzpW-0003jg-6r for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:20:15 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzpS-0005Zq-V3 for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:20:12 -0500 Received: from mail.maildlp.com (unknown [172.18.186.216]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7jf4XCKz6J67k; Mon, 5 Feb 2024 22:16:54 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id 4EC2C140D1A; Mon, 5 Feb 2024 22:20:07 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:20:06 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 01/11] hw/pci: Add pcie_find_dvsec() utility. Date: Mon, 5 Feb 2024 14:19:30 +0000 Message-ID: <20240205141940.31111-2-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Simple search code used to find first instance of a PCIe Designated Vendor-Specific Extended Capability. Signed-off-by: Jonathan Cameron --- include/hw/pci/pcie.h | 1 + hw/pci/pcie.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index 11f5a91bbb..ff559a6653 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -127,6 +127,7 @@ bool pcie_cap_is_arifwd_enabled(const PCIDevice *dev); /* PCI express extended capability helper functions */ uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id); +uint16_t pcie_find_dvsec(PCIDevice *dev, uint16_t vid, uint16_t id); void pcie_add_capability(PCIDevice *dev, uint16_t cap_id, uint8_t cap_ver, uint16_t offset, uint16_t size); diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 6db0cf69cd..9f1ca718b5 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -944,6 +944,30 @@ uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id) return pcie_find_capability_list(dev, cap_id, NULL); } +uint16_t pcie_find_dvsec(PCIDevice *dev, uint16_t vid, uint16_t id) +{ + uint16_t prev = 0; + uint16_t next; + + while (1) { + uint32_t head1; + + next = pcie_find_capability_list(dev, 0x23, &prev); + if (!next) { + break; + } + head1 = pci_get_long(dev->config + next + 4); + if ((head1 & 0xFFFF) == vid) { + uint16_t head2 = pci_get_word(dev->config + next + 8); + if (head2 == id) { + return next; + } + } + prev = next; + } + return 0; +} + static void pcie_ext_cap_set_next(PCIDevice *dev, uint16_t pos, uint16_t next) { uint32_t header = pci_get_long(dev->config + pos); From patchwork Mon Feb 5 14:19:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545615 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 76CCEC4828D for ; Mon, 5 Feb 2024 14:21:03 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzq0-0004UV-7q; Mon, 05 Feb 2024 09:20:44 -0500 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 1rWzpz-0004PL-4t for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:20:43 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzpw-0007N4-D3 for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:20:42 -0500 Received: from mail.maildlp.com (unknown [172.18.186.231]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7kC5Shxz6K9Bl; Mon, 5 Feb 2024 22:17:23 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id D9232140A9C; Mon, 5 Feb 2024 22:20:37 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:20:37 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 02/11] hw/acpi: Allow GPEX _OSC to keep fw first control of AER and CXL errors. Date: Mon, 5 Feb 2024 14:19:31 +0000 Message-ID: <20240205141940.31111-3-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Signed-off-by: Jonathan Cameron --- include/hw/acpi/cxl.h | 2 +- include/hw/pci-host/gpex.h | 1 + hw/acpi/cxl-stub.c | 2 +- hw/acpi/cxl.c | 31 +++++++++++++++++++++++++++---- hw/i386/acpi-build.c | 2 +- hw/pci-host/gpex-acpi.c | 17 +++++++++++------ hw/pci-host/gpex.c | 1 + 7 files changed, 43 insertions(+), 13 deletions(-) diff --git a/include/hw/acpi/cxl.h b/include/hw/acpi/cxl.h index 8f22c71530..38714147ec 100644 --- a/include/hw/acpi/cxl.h +++ b/include/hw/acpi/cxl.h @@ -24,7 +24,7 @@ void cxl_build_cedt(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, const char *oem_id, const char *oem_table_id, CXLState *cxl_state); -void build_cxl_osc_method(Aml *dev); +void build_cxl_osc_method(Aml *dev, bool fw_first); void build_cxl_dsm_method(Aml *dev); #endif diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h index dce883573b..866ae71ba0 100644 --- a/include/hw/pci-host/gpex.h +++ b/include/hw/pci-host/gpex.h @@ -47,6 +47,7 @@ struct GPEXConfig { MemMapEntry pio; int irq; PCIBus *bus; + bool fw_first_ras; }; struct GPEXHost { diff --git a/hw/acpi/cxl-stub.c b/hw/acpi/cxl-stub.c index 15bc21076b..0ec5c48850 100644 --- a/hw/acpi/cxl-stub.c +++ b/hw/acpi/cxl-stub.c @@ -6,7 +6,7 @@ #include "hw/acpi/aml-build.h" #include "hw/acpi/cxl.h" -void build_cxl_osc_method(Aml *dev) +void build_cxl_osc_method(Aml *dev, bool fw_first) { g_assert_not_reached(); } diff --git a/hw/acpi/cxl.c b/hw/acpi/cxl.c index d0e6a4b45e..526cfe961a 100644 --- a/hw/acpi/cxl.c +++ b/hw/acpi/cxl.c @@ -27,6 +27,7 @@ #include "hw/acpi/aml-build.h" #include "hw/acpi/bios-linker-loader.h" #include "hw/acpi/cxl.h" +#include "hw/acpi/ghes.h" #include "qapi/error.h" #include "qemu/uuid.h" @@ -222,11 +223,12 @@ void cxl_build_cedt(GArray *table_offsets, GArray *table_data, acpi_table_end(linker, &table); } -static Aml *__build_cxl_osc_method(void) +static Aml *__build_cxl_osc_method(bool fw_first) { Aml *method, *if_uuid, *else_uuid, *if_arg1_not_1, *if_cxl, *if_caps_masked; Aml *a_ctrl = aml_local(0); Aml *a_cdw1 = aml_name("CDW1"); + Aml *cxl_ctrl = aml_local(2); method = aml_method("_OSC", 4, AML_NOTSERIALIZED); /* CDW1 is used for the return value so is present whether or not a match occurs */ @@ -260,7 +262,11 @@ static Aml *__build_cxl_osc_method(void) * Allows OS control for all 5 features: * PCIeHotplug SHPCHotplug PME AER PCIeCapability */ - aml_append(if_uuid, aml_and(a_ctrl, aml_int(0x1F), a_ctrl)); + if (fw_first) { + aml_append(if_uuid, aml_and(a_ctrl, aml_int(0x17), a_ctrl)); + } else { + aml_append(if_uuid, aml_and(a_ctrl, aml_int(0x1F), a_ctrl)); + } /* * Check _OSC revision. @@ -290,6 +296,23 @@ static Aml *__build_cxl_osc_method(void) aml_append(if_cxl, aml_create_dword_field(aml_arg(3), aml_int(12), "CDW4")); /* CXL capabilities */ aml_append(if_cxl, aml_create_dword_field(aml_arg(3), aml_int(16), "CDW5")); + + aml_append(if_cxl, aml_store(aml_name("CDW5"), cxl_ctrl)); + if (fw_first) { + aml_append(if_cxl, aml_and(cxl_ctrl, aml_int(0x0), cxl_ctrl)); + } else { + /* Only allow CXL Memory Error Reporting */ + aml_append(if_cxl, aml_and(cxl_ctrl, aml_int(0x1), cxl_ctrl)); + } + + if_caps_masked = aml_if(aml_lnot(aml_equal(aml_name("CDW5"), cxl_ctrl))); + + /* Capability bits were masked */ + aml_append(if_caps_masked, aml_or(a_cdw1, aml_int(0x10), a_cdw1)); + aml_append(if_cxl, if_caps_masked); + + aml_append(if_cxl, aml_store(cxl_ctrl, aml_name("CDW5"))); + aml_append(if_cxl, aml_store(aml_name("CDW4"), aml_name("SUPC"))); aml_append(if_cxl, aml_store(aml_name("CDW5"), aml_name("CTRC"))); @@ -316,11 +339,11 @@ static Aml *__build_cxl_osc_method(void) return method; } -void build_cxl_osc_method(Aml *dev) +void build_cxl_osc_method(Aml *dev, bool fw_first) { aml_append(dev, aml_name_decl("SUPP", aml_int(0))); aml_append(dev, aml_name_decl("CTRL", aml_int(0))); aml_append(dev, aml_name_decl("SUPC", aml_int(0))); aml_append(dev, aml_name_decl("CTRC", aml_int(0))); - aml_append(dev, __build_cxl_osc_method()); + aml_append(dev, __build_cxl_osc_method(fw_first)); } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 58e4c54f31..2fbac1d826 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1655,7 +1655,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(aml_pkg, aml_eisaid("PNP0A08")); aml_append(aml_pkg, aml_eisaid("PNP0A03")); aml_append(dev, aml_name_decl("_CID", aml_pkg)); - build_cxl_osc_method(dev); + build_cxl_osc_method(dev, false); } else if (pci_bus_is_express(bus)) { aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); diff --git a/hw/pci-host/gpex-acpi.c b/hw/pci-host/gpex-acpi.c index f69413ea2c..f003669975 100644 --- a/hw/pci-host/gpex-acpi.c +++ b/hw/pci-host/gpex-acpi.c @@ -49,7 +49,7 @@ static void acpi_dsdt_add_pci_route_table(Aml *dev, uint32_t irq) } } -static void acpi_dsdt_add_pci_osc(Aml *dev) +static void acpi_dsdt_add_pci_osc(Aml *dev, bool fw_first_aer) { Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf; @@ -79,8 +79,13 @@ static void acpi_dsdt_add_pci_osc(Aml *dev) * Allow OS control for all 5 features: * PCIeHotplug SHPCHotplug PME AER PCIeCapability. */ - aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1F), - aml_name("CTRL"))); + if (fw_first_aer) { + aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x17), + aml_name("CTRL"))); + } else { + aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1F), + aml_name("CTRL"))); + } ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1)))); aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x08), @@ -186,9 +191,9 @@ void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg) aml_append(dev, aml_name_decl("_CRS", crs)); if (is_cxl) { - build_cxl_osc_method(dev); + build_cxl_osc_method(dev, cfg->fw_first_ras); } else { - acpi_dsdt_add_pci_osc(dev); + acpi_dsdt_add_pci_osc(dev, cfg->fw_first_ras); } aml_append(scope, dev); @@ -263,7 +268,7 @@ void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg) } aml_append(dev, aml_name_decl("_CRS", rbuf)); - acpi_dsdt_add_pci_osc(dev); + acpi_dsdt_add_pci_osc(dev, cfg->fw_first_ras); Aml *dev_res0 = aml_device("%s", "RES0"); aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02"))); diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c index e9cf455bf5..49fc69eec6 100644 --- a/hw/pci-host/gpex.c +++ b/hw/pci-host/gpex.c @@ -166,6 +166,7 @@ static Property gpex_host_properties[] = { gpex_cfg.mmio64.base, 0), DEFINE_PROP_SIZE(PCI_HOST_ABOVE_4G_MMIO_SIZE, GPEXHost, gpex_cfg.mmio64.size, 0), + DEFINE_PROP_BOOL("fw_first_ras", GPEXHost, gpex_cfg.fw_first_ras, false), DEFINE_PROP_END_OF_LIST(), }; From patchwork Mon Feb 5 14:19:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545616 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 9E88BC4828D for ; Mon, 5 Feb 2024 14:21:21 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzqT-0005Uu-Ji; Mon, 05 Feb 2024 09:21:14 -0500 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 1rWzqS-0005Tu-4O for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:21:12 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzqQ-0000Pw-3n for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:21:11 -0500 Received: from mail.maildlp.com (unknown [172.18.186.31]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7kr0Ddtz6J66x; Mon, 5 Feb 2024 22:17:56 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id 4FAC1140A87; Mon, 5 Feb 2024 22:21:08 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:21:07 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 03/11] arm/virt: Add fw-first-ras property. Date: Mon, 5 Feb 2024 14:19:32 +0000 Message-ID: <20240205141940.31111-4-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Provide a machine parameter to request firmware first RAS handling and no hand over to the OS via _OSC. Includes a bug fix as register access is not in CDW5 but only in CXW4 (OS support field). Signed-off-by: Jonathan Cameron --- include/hw/arm/virt.h | 1 + hw/acpi/cxl.c | 3 --- hw/arm/virt-acpi-build.c | 1 + hw/arm/virt.c | 20 ++++++++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 0a14551f19..84323ccb32 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -153,6 +153,7 @@ struct VirtMachineState { bool tcg_its; bool virt; bool ras; + bool fw_first_ras; bool mte; bool dtb_randomness; OnOffAuto acpi; diff --git a/hw/acpi/cxl.c b/hw/acpi/cxl.c index 526cfe961a..1d6dadbddd 100644 --- a/hw/acpi/cxl.c +++ b/hw/acpi/cxl.c @@ -316,9 +316,6 @@ static Aml *__build_cxl_osc_method(bool fw_first) aml_append(if_cxl, aml_store(aml_name("CDW4"), aml_name("SUPC"))); aml_append(if_cxl, aml_store(aml_name("CDW5"), aml_name("CTRC"))); - /* CXL 2.0 Port/Device Register access */ - aml_append(if_cxl, - aml_or(aml_name("CDW5"), aml_int(0x1), aml_name("CDW5"))); aml_append(if_uuid, if_cxl); aml_append(if_uuid, aml_return(aml_arg(3))); diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index e5f6996111..cdc0bca729 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -208,6 +208,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, .ecam = memmap[ecam_id], .irq = irq, .bus = vms->bus, + .fw_first_ras = vms->fw_first_ras, }; if (vms->highmem_mmio) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 14d3b66657..c1c8a514d7 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2864,6 +2864,20 @@ static void virt_set_ras(Object *obj, bool value, Error **errp) vms->ras = value; } +static bool virt_get_fw_first_ras(Object *obj, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + return vms->fw_first_ras; +} + +static void virt_set_fw_first_ras(Object *obj, bool value, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + vms->fw_first_ras = value; +} + static bool virt_get_mte(Object *obj, Error **errp) { VirtMachineState *vms = VIRT_MACHINE(obj); @@ -3400,6 +3414,12 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) "Set on/off to enable/disable reporting host memory errors " "to a KVM guest using ACPI and guest external abort exceptions"); + object_class_property_add_bool(oc, "fw-first-ras", virt_get_fw_first_ras, + virt_set_fw_first_ras); + object_class_property_set_description(oc, "fw-first-ras", + "Set on/off to control PCI/CXL _OSC allow the guest to" + "obtain permission to do native handling of AER and CXL errors"); + object_class_property_add_bool(oc, "mte", virt_get_mte, virt_set_mte); object_class_property_set_description(oc, "mte", "Set on/off to enable/disable emulating a " From patchwork Mon Feb 5 14:19:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545617 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 3873AC48295 for ; Mon, 5 Feb 2024 14:22:00 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzqz-0006BT-1u; Mon, 05 Feb 2024 09:21:45 -0500 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 1rWzqw-0006Ax-RB for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:21:42 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzqv-0001pv-0H for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:21:42 -0500 Received: from mail.maildlp.com (unknown [172.18.186.216]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7lQ4G07z6J67D; Mon, 5 Feb 2024 22:18:26 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id D0B4E140B73; Mon, 5 Feb 2024 22:21:38 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:21:38 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 04/11] acpi/ghes: Support GPIO error source. Date: Mon, 5 Feb 2024 14:19:33 +0000 Message-ID: <20240205141940.31111-5-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Signed-off-by: Jonathan Cameron --- include/hw/acpi/ghes.h | 1 + hw/acpi/ghes.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 674f6958e9..4f1ab1a73a 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -58,6 +58,7 @@ enum AcpiGhesNotifyType { enum { ACPI_HEST_SRC_ID_SEA = 0, + ACPI_HEST_SRC_ID_GPIO = 1, /* future ids go here */ ACPI_HEST_SRC_ID_RESERVED, }; diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index e9511d9b8f..5b8bc6eeb4 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -34,8 +34,8 @@ /* The max size in bytes for one error block */ #define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB) -/* Now only support ARMv8 SEA notification type error source */ -#define ACPI_GHES_ERROR_SOURCE_COUNT 1 +/* Support ARMv8 SEA notification type error source and GPIO interrupt. */ +#define ACPI_GHES_ERROR_SOURCE_COUNT 2 /* Generic Hardware Error Source version 2 */ #define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10 @@ -327,6 +327,9 @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) */ build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA); break; + case ACPI_HEST_SRC_ID_GPIO: + build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_GPIO); + break; default: error_report("Not support this error source"); abort(); @@ -370,6 +373,7 @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker, /* Error Source Count */ build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4); build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker); + build_ghes_v2(table_data, ACPI_HEST_SRC_ID_GPIO, linker); acpi_table_end(linker, &table); } From patchwork Mon Feb 5 14:19:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545618 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 BDA1AC48295 for ; Mon, 5 Feb 2024 14:22:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzrV-0006hj-RM; Mon, 05 Feb 2024 09:22:17 -0500 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 1rWzrS-0006fs-Mw for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:22:14 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzrQ-0003Me-F3 for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:22:14 -0500 Received: from mail.maildlp.com (unknown [172.18.186.231]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7lb2S0lz6JB87; Mon, 5 Feb 2024 22:18:35 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id 885831404F5; Mon, 5 Feb 2024 22:22:09 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:22:09 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 05/11] arm/virt: Wire up GPIO error source for ACPI / GHES Date: Mon, 5 Feb 2024 14:19:34 +0000 Message-ID: <20240205141940.31111-6-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Includes creation of a GED - Generic Event Device Signed-off-by: Jonathan Cameron --- include/hw/boards.h | 1 + hw/arm/virt-acpi-build.c | 29 +++++++++++++++++++++++++---- hw/arm/virt.c | 12 +++++++++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index bcfde8a84d..a9badd9fd2 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -301,6 +301,7 @@ struct MachineClass { const CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine); int64_t (*get_default_cpu_node_id)(const MachineState *ms, int idx); ram_addr_t (*fixup_ram_size)(ram_addr_t size); + void (*set_error)(void); }; /** diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index cdc0bca729..297fa5f8b2 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -64,6 +64,7 @@ #define ARM_SPI_BASE 32 +#define ACPI_GENERIC_EVENT_DEVICE "GEDD" #define ACPI_BUILD_TABLE_SIZE 0x20000 static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) @@ -242,9 +243,14 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, Aml *aei = aml_resource_template(); /* Pin 3 for power button */ - const uint32_t pin_list[1] = {3}; + uint32_t pin = 3; aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1, + AML_EXCLUSIVE, AML_PULL_UP, 0, &pin, 1, + "GPO0", NULL, 0)); + pin = 6; + /* Pin 8 for generic error */ + aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, AML_PULL_UP, 0, &pin, 1, "GPO0", NULL, 0)); aml_append(dev, aml_name_decl("_AEI", aei)); @@ -253,6 +259,11 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), aml_int(0x80))); aml_append(dev, method); + method = aml_method("_E06", 0, AML_NOTSERIALIZED); + aml_append(method, aml_notify(aml_name(ACPI_GENERIC_EVENT_DEVICE), + aml_int(0x80))); + aml_append(dev, method); + aml_append(scope, dev); } @@ -885,6 +896,15 @@ static void build_fadt_rev6(GArray *table_data, BIOSLinker *linker, build_fadt(table_data, linker, &fadt, vms->oem_id, vms->oem_table_id); } +static void acpi_dsdt_add_generic_event_device(Aml *scope) +{ + Aml *dev = aml_device(ACPI_GENERIC_EVENT_DEVICE); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C33"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); + aml_append(scope, dev); +} + /* DSDT */ static void build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) @@ -926,9 +946,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, memmap[VIRT_ACPI_GED].base); } else { - acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], - (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); } + acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], + (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); if (vms->acpi_dev) { uint32_t event = object_property_get_uint(OBJECT(vms->acpi_dev), @@ -942,6 +962,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) } acpi_dsdt_add_power_button(scope); + acpi_dsdt_add_generic_event_device(scope); #ifdef CONFIG_TPM acpi_dsdt_add_tpm(scope, vms); #endif diff --git a/hw/arm/virt.c b/hw/arm/virt.c index c1c8a514d7..c87dc5acce 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -914,6 +914,13 @@ static void create_rtc(const VirtMachineState *vms) } static DeviceState *gpio_key_dev; + +static DeviceState *gpio_error_dev; +static void virt_set_error(void) +{ + qemu_set_irq(qdev_get_gpio_in(gpio_error_dev, 0), 1); +} + static void virt_powerdown_req(Notifier *n, void *opaque) { VirtMachineState *s = container_of(n, VirtMachineState, powerdown_notifier); @@ -931,6 +938,8 @@ static void create_gpio_keys(char *fdt, DeviceState *pl061_dev, { gpio_key_dev = sysbus_create_simple("gpio-key", -1, qdev_get_gpio_in(pl061_dev, 3)); + gpio_error_dev = sysbus_create_simple("gpio-key", -1, + qdev_get_gpio_in(pl061_dev, 6)); qemu_fdt_add_subnode(fdt, "/gpio-keys"); qemu_fdt_setprop_string(fdt, "/gpio-keys", "compatible", "gpio-keys"); @@ -2606,8 +2615,8 @@ static void machvirt_init(MachineState *machine) if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) { vms->acpi_dev = create_acpi_ged(vms); } else { - create_gpio_devices(vms, VIRT_GPIO, sysmem); } + create_gpio_devices(vms, VIRT_GPIO, sysmem); if (vms->secure && !vmc->no_secure_gpio) { create_gpio_devices(vms, VIRT_SECURE_GPIO, secure_sysmem); @@ -3337,6 +3346,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->default_ram_id = "mach-virt.ram"; mc->default_nic = "virtio-net-pci"; + mc->set_error = virt_set_error; object_class_property_add(oc, "acpi", "OnOffAuto", virt_get_acpi, virt_set_acpi, NULL, NULL); From patchwork Mon Feb 5 14:19:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545619 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 05447C4828D for ; Mon, 5 Feb 2024 14:22:51 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzrw-0007Lc-Us; Mon, 05 Feb 2024 09:22:44 -0500 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 1rWzrw-0007LI-4V for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:22:44 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzrt-00051A-PK for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:22:43 -0500 Received: from mail.maildlp.com (unknown [172.18.186.231]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7mb4xTgz6J66m; Mon, 5 Feb 2024 22:19:27 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id F2A0D1404F5; Mon, 5 Feb 2024 22:22:39 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:22:39 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 06/11] acpi: pci/cxl: Stash the OSC control parameters. Date: Mon, 5 Feb 2024 14:19:35 +0000 Message-ID: <20240205141940.31111-7-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Allow QEMU to know what was successfully requested by the OS via _OSC. Note this handling is very minimal and assumes last written Control parameters were accepted (which they should be if the OS is obeying the rules for negotiating this stuff). Signed-off-by: Jonathan Cameron --- include/hw/acpi/ghes.h | 3 +++ hw/acpi/cxl.c | 16 +++++++++++++++ hw/acpi/ghes-stub.c | 10 +++++++++ hw/acpi/ghes.c | 44 ++++++++++++++++++++++++++++++++++++++++ hw/arm/virt-acpi-build.c | 41 ++++++++++++++++++++++++++++++++++++- 5 files changed, 113 insertions(+), 1 deletion(-) diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 4f1ab1a73a..3210c19c14 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -66,6 +66,7 @@ enum { typedef struct AcpiGhesState { uint64_t ghes_addr_le; bool present; /* True if GHES is present at all on this board */ + uint64_t pci_osc_addr_le; } AcpiGhesState; void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker); @@ -82,4 +83,6 @@ int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr); * safe to call acpi_ghes_record_errors() to record a memory error. */ bool acpi_ghes_present(void); +bool acpi_fw_first_pci(void); +bool acpi_fw_first_cxl_mem(void); #endif diff --git a/hw/acpi/cxl.c b/hw/acpi/cxl.c index 1d6dadbddd..2ce3488943 100644 --- a/hw/acpi/cxl.c +++ b/hw/acpi/cxl.c @@ -228,11 +228,27 @@ static Aml *__build_cxl_osc_method(bool fw_first) Aml *method, *if_uuid, *else_uuid, *if_arg1_not_1, *if_cxl, *if_caps_masked; Aml *a_ctrl = aml_local(0); Aml *a_cdw1 = aml_name("CDW1"); + Aml *cxl_osc_mem = aml_local(1); Aml *cxl_ctrl = aml_local(2); + Aml *field; + method = aml_method("_OSC", 4, AML_NOTSERIALIZED); /* CDW1 is used for the return value so is present whether or not a match occurs */ aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); + if (acpi_ghes_present()) { + aml_append(method, aml_store(aml_name("COSC"), cxl_osc_mem)); + aml_append(method, aml_operation_region("CXLA", AML_SYSTEM_MEMORY, + cxl_osc_mem, 64)); + + field = aml_field("CXLA", AML_DWORD_ACC, AML_NOLOCK, AML_PRESERVE); + aml_append(field, aml_named_field("ODW1", 32)); + aml_append(field, aml_named_field("ODW2", 32)); + aml_append(method, field); + /* Store the value for querying later */ + aml_append(method, aml_store(aml_name("CTRL"), aml_name("ODW1"))); + aml_append(method, aml_store(aml_name("CTRC"), aml_name("ODW2"))); + } /* * Generate shared section between: diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c index c315de1802..1ad7b9f776 100644 --- a/hw/acpi/ghes-stub.c +++ b/hw/acpi/ghes-stub.c @@ -20,3 +20,13 @@ bool acpi_ghes_present(void) { return false; } + +bool acpi_fw_first_pci(void) +{ + return false; +} + +bool acpi_fw_first_cxl_mem(void) +{ + return false; +} diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index 5b8bc6eeb4..9f99202e1f 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -462,3 +462,47 @@ bool acpi_ghes_present(void) ags = &acpi_ged_state->ghes_state; return ags->present; } + +bool acpi_fw_first_pci(void) +{ + if (acpi_ghes_present()) { + AcpiGhesState *ags = + &ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, + NULL))->ghes_state; + uint32_t pci_osc; + + cpu_physical_memory_read(le64_to_cpu(ags->pci_osc_addr_le), + &pci_osc, sizeof(pci_osc)); + if (pci_osc == 0) { + printf("OSC not called yet\n"); + return true; /* OSC not run yet */ + } + printf("OSC has been called %x\n", pci_osc); + return !(pci_osc & (1 << 3)); + } + return false; +} + +bool acpi_fw_first_cxl_mem(void) +{ + if (!acpi_fw_first_pci()) { + return false; + } + if (acpi_ghes_present()) { + AcpiGhesState *ags = + &ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, + NULL))->ghes_state; + uint32_t cxl_osc; + + cpu_physical_memory_read(le64_to_cpu(ags->pci_osc_addr_le) + + sizeof(uint32_t), + &cxl_osc, sizeof(cxl_osc)); + if (cxl_osc == 0) { + printf("CXL OSC not called yet or memory error not requested\n"); + return true; /* OSC not run yet */ + } + printf("OSC has been called %x\n", cxl_osc); + return !(cxl_osc & (1 << 0)); + } + return false; +} diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 297fa5f8b2..93ec095b0f 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -916,6 +916,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) const int *irqmap = vms->irqmap; AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = vms->oem_id, .oem_table_id = vms->oem_table_id }; + int mem_addr_offset; acpi_table_begin(&table, table_data); dsdt = init_aml_allocator(); @@ -972,6 +973,16 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) /* copy AML table into ACPI tables blob */ g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); + /* Outside of the DSDT creation because we need the final address */ + mem_addr_offset = build_append_named_dword(table_data, "COSC"); + /* Patch COSC to point to the cxl-osc FW_CFG file */ + bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, + mem_addr_offset, sizeof(uint32_t), + "etc/acpi/cxl-osc", 0); + /* Store address of cxl-osc FW_CFG file in cxl-osc-addr FW_CFG file */ + bios_linker_loader_write_pointer(linker, "etc/acpi/cxl-osc-addr", 0, + sizeof(uint64_t), "etc/acpi/cxl-osc", 0); + acpi_table_end(linker, &table); free_aml_allocator(); } @@ -995,6 +1006,8 @@ static void acpi_align_size(GArray *blob, unsigned align) g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); } +static GArray *test; + static void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) { @@ -1004,6 +1017,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) GArray *tables_blob = tables->table_data; MachineState *ms = MACHINE(vms); + /* Load the cxl-osc FW_CFG file into guest memory */ + bios_linker_loader_alloc(tables->linker, "etc/acpi/cxl-osc", + test, 64, false); + table_offsets = g_array_new(false, true /* clear */, sizeof(uint32_t)); @@ -1202,6 +1219,10 @@ void virt_acpi_setup(VirtMachineState *vms) build_state = g_malloc0(sizeof *build_state); + test = g_array_new(false, true, 4); + acpi_data_push(test, sizeof(uint64_t)); + *((uint64_t *)test->data) = 0xdeadbeefdeadbeef; + acpi_build_tables_init(&tables); virt_acpi_build(vms, &tables); @@ -1234,7 +1255,25 @@ void virt_acpi_setup(VirtMachineState *vms) virt_acpi_build_reset(build_state); vmstate_register(NULL, 0, &vmstate_virt_acpi_build, build_state); - /* Cleanup tables but don't free the memory: we track it + if (acpi_ghes_present()) { + AcpiGhesState *ags = + &ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, + NULL))->ghes_state; + + /* Add a cxl-osc FW_CFG file that will be used to stash osc outcomes */ + fw_cfg_add_file(vms->fw_cfg, "etc/acpi/cxl-osc", + test->data, test->len); + /* + * Add a cxl-osc-addr FW_CFG file that will be used to get to the + * address of cxl-osc FW_CFG file. Can be written by FW. + */ + fw_cfg_add_file_callback(vms->fw_cfg, "etc/acpi/cxl-osc-addr", + NULL, NULL, NULL, + &ags->pci_osc_addr_le, sizeof(uint64_t), + false); + } + /* + * Cleanup tables but don't free the memory: we track it * in build_state. */ acpi_build_tables_cleanup(&tables, false); From patchwork Mon Feb 5 14:19:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545620 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 44884C4828D for ; Mon, 5 Feb 2024 14:23:30 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzsV-0007vD-K4; Mon, 05 Feb 2024 09:23:19 -0500 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 1rWzsT-0007v5-Ol for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:23:18 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzsP-0006cJ-Bu for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:23:17 -0500 Received: from mail.maildlp.com (unknown [172.18.186.216]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7mm2Fq4z6JB8F; Mon, 5 Feb 2024 22:19:36 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id 7CA251404FC; Mon, 5 Feb 2024 22:23:10 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:23:10 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 07/11] pci/aer: Support firmware first error injection via GHESv2 Date: Mon, 5 Feb 2024 14:19:36 +0000 Message-ID: <20240205141940.31111-8-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org If the machine supports firmware first error injection enable those flows. Signed-off-by: Jonathan Cameron --- include/hw/acpi/ghes.h | 3 + hw/acpi/ghes-stub.c | 4 + hw/acpi/ghes.c | 250 +++++++++++++++++++++++++++++++++++++++-- hw/pci/pcie_aer.c | 35 ++++-- 4 files changed, 271 insertions(+), 21 deletions(-) diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 3210c19c14..437aeae7f6 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -76,6 +76,9 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s, GArray *hardware_errors); int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr); +typedef struct PCIDevice PCIDevice; +bool ghes_record_aer_errors(PCIDevice *dev, uint32_t notify); + /** * acpi_ghes_present: Report whether ACPI GHES table is present * diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c index 1ad7b9f776..bd208af4ec 100644 --- a/hw/acpi/ghes-stub.c +++ b/hw/acpi/ghes-stub.c @@ -11,6 +11,10 @@ #include "qemu/osdep.h" #include "hw/acpi/ghes.h" +bool ghes_record_aer_errors(PCIDevice *dev, uint32_t notify) +{ + return true; +} int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) { return -1; diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index 9f99202e1f..d0103c0a6a 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -26,6 +26,8 @@ #include "qemu/error-report.h" #include "hw/acpi/generic_event_device.h" #include "hw/nvram/fw_cfg.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_device.h" #include "qemu/uuid.h" #define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" @@ -52,6 +54,7 @@ /* The memory section CPER size, UEFI 2.6: N.2.5 Memory Error Section */ #define ACPI_GHES_MEM_CPER_LENGTH 80 +#define ACPI_GHES_PCIE_CPER_LENGTH 208 /* Masks for block_status flags */ #define ACPI_GEBS_UNCORRECTABLE 1 @@ -184,6 +187,98 @@ static void acpi_ghes_build_append_mem_cper(GArray *table, build_append_int_noprefix(table, 0, 7); } +static void build_append_aer_cper(PCIDevice *dev, GArray *table) +{ + PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(dev); + uint16_t pcie_cap_offset = pci_find_capability(dev, 0x10); + uint16_t sn_cap_offset = pcie_find_capability(dev, 0x3); + uint16_t aer_cap_offset = pcie_find_capability(dev, 0x1); + int i; + + build_append_int_noprefix(table, + /* Port Type */ + ((pcie_cap_offset ? 1UL : 0UL) << 0) | + /* PCI Express Version */ + (1UL << 1) | + /* Command Status */ + (1UL << 2) | + /* Device ID valid */ + (1UL << 3) | + /* Serial Number */ + ((sn_cap_offset ? 1UL : 0UL) << 4) | + /* Whole PCIe Capability */ + ((pcie_cap_offset ? 1UL : 0UL) << 6) | + /* AER capability */ + ((aer_cap_offset ? 1UL : 0UL) << 7), + 8); + if (pcie_cap_offset) { + uint16_t cap_reg = pci_get_word(dev->config + pcie_cap_offset + + PCI_EXP_FLAGS); + uint16_t port_type = (cap_reg & PCI_EXP_FLAGS_TYPE) >> + PCI_EXP_FLAGS_TYPE_SHIFT; + + build_append_int_noprefix(table, port_type, 4); + } + build_append_int_noprefix(table, 1, 1); /* Version PCIE r6.1 */ + build_append_int_noprefix(table, 6, 1); + build_append_int_noprefix(table, 0, 2); /* Reserved */ + + build_append_int_noprefix(table, + pci_get_word(dev->config + PCI_COMMAND), 2); + build_append_int_noprefix(table, pci_get_word(dev->config + PCI_STATUS), 2); + build_append_int_noprefix(table, 0, 4); /* 20-23 reserved */ + + build_append_int_noprefix(table, pci_class->vendor_id, 2); + build_append_int_noprefix(table, pci_class->device_id, 2); + build_append_int_noprefix(table, pci_class->class_id, 3); + build_append_int_noprefix(table, PCI_FUNC(dev->devfn), 1); + build_append_int_noprefix(table, PCI_SLOT(dev->devfn), 1); + build_append_int_noprefix(table, 0, 2); /* Segment number */ + + /* RP/B primary bus number / device bus number */ + build_append_int_noprefix(table, pci_dev_bus_num(dev), 1); + build_append_int_noprefix(table, 0, 1); + /* + * TODO: Figure out where to get the slot number from. + * The slot number capability is deprecated so it only really + * exists via the _DSM which is not easily available from here. + */ + build_append_int_noprefix(table, 0, 2); + build_append_int_noprefix(table, 0, 1); /* reserved */ + + /* Serial number */ + if (sn_cap_offset) { + uint32_t dw = pci_get_long(dev->config + sn_cap_offset + 4); + + build_append_int_noprefix(table, dw, 4); + dw = pci_get_long(dev->config + sn_cap_offset + 8); + build_append_int_noprefix(table, dw, 4); + } else { + build_append_int_noprefix(table, 0, 8); + } + + /* Bridge control status */ + build_append_int_noprefix(table, 0, 4); + + if (pcie_cap_offset) { + uint32_t *pcie_cap = (uint32_t *)(dev->config + pcie_cap_offset); + for (i = 0; i < 60 / sizeof(uint32_t); i++) { + build_append_int_noprefix(table, pcie_cap[i], sizeof(uint32_t)); + } + } else { /* Odd if we don't have one of these! */ + build_append_int_noprefix(table, 0, 60); + } + + if (aer_cap_offset) { + uint32_t *aer_cap = (uint32_t *)(dev->config + aer_cap_offset); + for (i = 0; i < 96 / sizeof(uint32_t); i++) { + build_append_int_noprefix(table, aer_cap[i], sizeof(uint32_t)); + } + } else { + build_append_int_noprefix(table, 0, 96); + } +} + static int acpi_ghes_record_mem_error(uint64_t error_block_address, uint64_t error_physical_addr) { @@ -231,6 +326,45 @@ static int acpi_ghes_record_mem_error(uint64_t error_block_address, return 0; } +static int ghes_record_aer_error(PCIDevice *dev, uint64_t error_block_address) +{ + const uint8_t aer_section_id_le[] = { + 0x54, 0xE9, 0x95, 0xD9, 0xC1, 0xBB, 0x0F, + 0x43, 0xAD, 0x91, 0xB4, 0x4D, 0xCB, 0x3C, + 0x6F, 0x35 }; + QemuUUID fru_id = { 0 }; + GArray *block = g_array_new(false, true, 1); + uint32_t data_length; + + /* Read the current length in bytes of the generic error data */ + cpu_physical_memory_read(error_block_address + 8, &data_length, 4); + + /* Add a new generic error data entry*/ + data_length += ACPI_GHES_DATA_LENGTH; + data_length += ACPI_GHES_PCIE_CPER_LENGTH; + + /* + * Check whether it will run out of the preallocated memory if adding a new + * generic error data entry + */ + if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) { + error_report("Record CPER out of boundary!!!"); + return false; + } + + acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE, 0, 0, + data_length, ACPI_CPER_SEV_RECOVERABLE); + acpi_ghes_generic_error_data(block, aer_section_id_le, + ACPI_CPER_SEV_RECOVERABLE, 0, 0, + ACPI_GHES_PCIE_CPER_LENGTH, fru_id, 0); + + build_append_aer_cper(dev, block); + cpu_physical_memory_write(error_block_address, block->data, block->len); + g_array_free(block, true); + + return true; +} + /* * Build table for the hardware error fw_cfg blob. * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs. @@ -392,23 +526,22 @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s, ags->present = true; } +static uint64_t ghes_get_state_start_address(void) +{ + AcpiGedState *acpi_ged_state = + ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, NULL)); + AcpiGhesState *ags = &acpi_ged_state->ghes_state; + + return le64_to_cpu(ags->ghes_addr_le); +} + int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) { uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0; - uint64_t start_addr; + uint64_t start_addr = ghes_get_state_start_address(); bool ret = -1; - AcpiGedState *acpi_ged_state; - AcpiGhesState *ags; - assert(source_id < ACPI_HEST_SRC_ID_RESERVED); - acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, - NULL)); - g_assert(acpi_ged_state); - ags = &acpi_ged_state->ghes_state; - - start_addr = le64_to_cpu(ags->ghes_addr_le); - if (physical_address) { if (source_id < ACPI_HEST_SRC_ID_RESERVED) { @@ -448,6 +581,101 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) return ret; } +/* + * Error register block data layout + * + * | +---------------------+ ges.ghes_addr_le + * | |error_block_address0 | + * | +---------------------+ + * | |error_block_address1 | + * | +---------------------+ --+-- + * | | ............. | GHES_ADDRESS_SIZE + * | +---------------------+ --+-- + * | |error_block_addressN | + * | +---------------------+ + * | | read_ack_register0 | + * | +---------------------+ --+-- + * | | read_ack_register1 | GHES_ADDRESS_SIZE + * | +---------------------+ --+-- + * | | ............. | + * | +---------------------+ + * | | read_ack_registerN | + * | +---------------------+ --+-- + * | | CPER | | + * | | .... | GHES_MAX_RAW_DATA_LENGT + * | | CPER | | + * | +---------------------+ --+-- + * | | .......... | + * | +---------------------+ + * | | CPER | + * | | .... | + * | | CPER | + * | +---------------------+ + */ + +/* Map from uint32_t notify to entry offset in GHES */ +static const uint8_t error_source_to_index[] = { 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 1, 0}; + +static bool ghes_get_addr(uint32_t notify, uint64_t *error_block_addr, + uint64_t *read_ack_register_addr) +{ + uint64_t base; + + if (notify >= ACPI_GHES_NOTIFY_RESERVED) { + return false; + } + + /* Find and check the source id for this new CPER */ + if (error_source_to_index[notify] == 0xff) { + return false; + } + + base = ghes_get_state_start_address(); + + *read_ack_register_addr = base + + ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t) + + error_source_to_index[notify] * sizeof(uint64_t); + + /* Could also be read back from the error_block_address register */ + *error_block_addr = base + + ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t) + + ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t) + + error_source_to_index[notify] * ACPI_GHES_MAX_RAW_DATA_LENGTH; + + return true; +} + +bool ghes_record_aer_errors(PCIDevice *dev, uint32_t notify) +{ + int read_ack_register = 0; + uint64_t read_ack_register_addr = 0; + uint64_t error_block_addr = 0; + + if (!ghes_get_addr(notify, &error_block_addr, &read_ack_register_addr)) { + return false; + } + + cpu_physical_memory_read(read_ack_register_addr, &read_ack_register, + sizeof(uint64_t)); + /* zero means OSPM does not acknowledge the error */ + if (!read_ack_register) { + error_report("Last time OSPM does not acknowledge the error," + " record CPER failed this time, set the ack value to" + " avoid blocking next time CPER record! exit"); + read_ack_register = 1; + cpu_physical_memory_write(read_ack_register_addr, &read_ack_register, + sizeof(uint64_t)); + return false; + } + + read_ack_register = cpu_to_le64(0); + cpu_physical_memory_write(read_ack_register_addr, &read_ack_register, + sizeof(uint64_t)); + + return ghes_record_aer_error(dev, error_block_addr); +} + bool acpi_ghes_present(void) { AcpiGedState *acpi_ged_state; diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index 2c85a78fcd..414a9564c2 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "migration/vmstate.h" +#include "hw/boards.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pcie.h" #include "hw/pci/msix.h" @@ -27,6 +28,7 @@ #include "hw/pci/pci_bus.h" #include "hw/pci/pcie_regs.h" #include "pci-internal.h" +#include "hw/acpi/ghes.h" //#define DEBUG_PCIE #ifdef DEBUG_PCIE @@ -638,6 +640,8 @@ static bool pcie_aer_inject_uncor_error(PCIEAERInject *inj, bool is_fatal) */ int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err) { + MachineState *machine = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(machine); uint8_t *aer_cap = NULL; uint16_t devctl = 0; uint16_t devsta = 0; @@ -701,16 +705,27 @@ int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err) } /* send up error message */ - inj.msg.source_id = err->source_id; - pcie_aer_msg(dev, &inj.msg); - - if (inj.log_overflow) { - PCIEAERErr header_log_overflow = { - .status = PCI_ERR_COR_HL_OVERFLOW, - .flags = PCIE_AER_ERR_IS_CORRECTABLE, - }; - int ret = pcie_aer_inject_error(dev, &header_log_overflow); - assert(!ret); + if (!acpi_fw_first_pci()) { + inj.msg.source_id = err->source_id; + pcie_aer_msg(dev, &inj.msg); + + if (inj.log_overflow) { + PCIEAERErr header_log_overflow = { + .status = PCI_ERR_COR_HL_OVERFLOW, + .flags = PCIE_AER_ERR_IS_CORRECTABLE, + }; + int ret = pcie_aer_inject_error(dev, &header_log_overflow); + assert(!ret); + } + } else { + ghes_record_aer_errors(dev, ACPI_GHES_NOTIFY_GPIO); + if (mc->set_error) { + mc->set_error(); + } + /* Simulation a firmware clearing status */ + /* Bit hacky but we only injected one error so this should be fine */ + pci_set_long(aer_cap + PCI_ERR_UNCOR_STATUS, 0); + pci_set_long(aer_cap + PCI_ERR_COR_STATUS, 0); } return 0; } From patchwork Mon Feb 5 14:19:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545633 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 80BB2C48295 for ; Mon, 5 Feb 2024 14:23:59 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzsw-0008PB-QX; Mon, 05 Feb 2024 09:23:46 -0500 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 1rWzsu-0008JB-Jc for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:23:44 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzss-00086f-PR for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:23:44 -0500 Received: from mail.maildlp.com (unknown [172.18.186.231]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7nL5t8bz6JB1b; Mon, 5 Feb 2024 22:20:06 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id 084581404F5; Mon, 5 Feb 2024 22:23:41 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:23:40 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 08/11] hw/pci/aer: Default to error handling on. Date: Mon, 5 Feb 2024 14:19:37 +0000 Message-ID: <20240205141940.31111-9-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This should be dependent on the platform supporting FW first. Signed-off-by: Jonathan Cameron --- hw/pci/pcie.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 9f1ca718b5..4f04a1702a 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -304,6 +304,12 @@ void pcie_cap_deverr_init(PCIDevice *dev) uint32_t pos = dev->exp.exp_cap; pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCAP, PCI_EXP_DEVCAP_RBER); + + /* HACK - FW first settings - how to do this cleanly? */ + pci_long_test_and_set_mask(dev->config + pos + PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | + PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); + pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); From patchwork Mon Feb 5 14:19:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545634 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 E7400C4828D for ; Mon, 5 Feb 2024 14:24:22 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWztU-0000fC-LO; Mon, 05 Feb 2024 09:24:20 -0500 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 1rWztP-0000dn-2F for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:24:15 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWztN-00013N-9F for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:24:14 -0500 Received: from mail.maildlp.com (unknown [172.18.186.31]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7nx2FVLz6JB89; Mon, 5 Feb 2024 22:20:37 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id 80801140A87; Mon, 5 Feb 2024 22:24:11 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:24:10 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 09/11] cxl/ras: Set registers to sensible state for FW first ras Date: Mon, 5 Feb 2024 14:19:38 +0000 Message-ID: <20240205141940.31111-10-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Even if we are doing native RAS, until the point where the OS requests it via an _OSC the firmware may well be handling any errors from CXL devices. As such configure them as if a firmware has been doing so. Signed-off-by: Jonathan Cameron --- hw/cxl/cxl-component-utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c index a0ff7d4396..e869c482a7 100644 --- a/hw/cxl/cxl-component-utils.c +++ b/hw/cxl/cxl-component-utils.c @@ -217,13 +217,13 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk) stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_STATUS, 0); stl_le_p(write_msk + R_CXL_RAS_UNC_ERR_STATUS, 0x1cfff); /* Bits 12-13 and 17-31 reserved in CXL 2.0 */ - stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_MASK, 0x1cfff); + stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_MASK, 0/*0x1cfff*/); stl_le_p(write_msk + R_CXL_RAS_UNC_ERR_MASK, 0x1cfff); stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_SEVERITY, 0x1cfff); stl_le_p(write_msk + R_CXL_RAS_UNC_ERR_SEVERITY, 0x1cfff); stl_le_p(reg_state + R_CXL_RAS_COR_ERR_STATUS, 0); stl_le_p(write_msk + R_CXL_RAS_COR_ERR_STATUS, 0x7f); - stl_le_p(reg_state + R_CXL_RAS_COR_ERR_MASK, 0x7f); + stl_le_p(reg_state + R_CXL_RAS_COR_ERR_MASK, 0/*0x7f*/); stl_le_p(write_msk + R_CXL_RAS_COR_ERR_MASK, 0x7f); /* CXL switches and devices must set */ stl_le_p(reg_state + R_CXL_RAS_ERR_CAP_CTRL, 0x200); From patchwork Mon Feb 5 14:19:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545635 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 A4BD4C48295 for ; Mon, 5 Feb 2024 14:25:04 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzty-0001HO-LZ; Mon, 05 Feb 2024 09:24:50 -0500 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 1rWztw-0001H4-Aa for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:24:48 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzts-0002Yw-3H for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:24:47 -0500 Received: from mail.maildlp.com (unknown [172.18.186.216]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7px6mcZz6J68p; Mon, 5 Feb 2024 22:21:29 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id 407BA1404FC; Mon, 5 Feb 2024 22:24:42 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:24:41 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 10/11] cxl/type3: FW first protocol error injection. Date: Mon, 5 Feb 2024 14:19:39 +0000 Message-ID: <20240205141940.31111-11-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Note this is only hooked up to type 3 device so far. Injection via the same interface as for native errors. e.g. { "execute": "cxl-inject-uncorrectable-errors", "arguments": { "path": "/machine/peripheral/cxl-pmem2", "errors": [ { "type": "cache-address-parity", "header": [ 3, 4] } ] }} Signed-off-by: Jonathan Cameron --- include/hw/acpi/ghes.h | 4 + include/hw/cxl/cxl.h | 2 + hw/acpi/ghes-stub.c | 5 + hw/acpi/ghes.c | 212 ++++++++++++++++++++++++++++++++++ hw/mem/cxl_type3.c | 28 ++++- hw/pci-bridge/cxl_root_port.c | 1 - 6 files changed, 248 insertions(+), 4 deletions(-) diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 437aeae7f6..3426697ecd 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -79,6 +79,10 @@ int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr); typedef struct PCIDevice PCIDevice; bool ghes_record_aer_errors(PCIDevice *dev, uint32_t notify); +typedef struct CXLError CXLError; +bool ghes_record_cxl_errors(PCIDevice *dev, PCIEAERErr *err, + CXLError *cxl_err, uint32_t notify); + /** * acpi_ghes_present: Report whether ACPI GHES table is present * diff --git a/include/hw/cxl/cxl.h b/include/hw/cxl/cxl.h index 857fa61898..24b2166431 100644 --- a/include/hw/cxl/cxl.h +++ b/include/hw/cxl/cxl.h @@ -57,6 +57,8 @@ struct CXLHost { bool passthrough; }; +#define TYPE_CXL_ROOT_PORT "cxl-rp" + #define TYPE_PXB_CXL_HOST "pxb-cxl-host" OBJECT_DECLARE_SIMPLE_TYPE(CXLHost, PXB_CXL_HOST) diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c index bd208af4ec..cbc7d57465 100644 --- a/hw/acpi/ghes-stub.c +++ b/hw/acpi/ghes-stub.c @@ -19,6 +19,11 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) { return -1; } +bool ghes_record_cxl_errors(PCIDevice *dev, PCIEAERErr *err, + CXLError *cxl_err, uint32_t notify) +{ + return false; +} bool acpi_ghes_present(void) { diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index d0103c0a6a..c6e863d375 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -29,6 +29,8 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_device.h" #include "qemu/uuid.h" +#include "hw/cxl/cxl_device.h" +#include "hw/cxl/cxl.h" #define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors" #define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr" @@ -279,6 +281,140 @@ static void build_append_aer_cper(PCIDevice *dev, GArray *table) } } +static void build_append_cxl_cper(PCIDevice *dev, CXLError *cxl_err, + GArray *table) +{ + PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(dev); + uint16_t sn_cap_offset = pcie_find_capability(dev, 0x3); + uint16_t pcie_cap_offset = pci_find_capability(dev, 0x10); + uint16_t cxl_dvsec_offset; + uint16_t cxl_dvsec_len = 0; + uint8_t type = 0xff; + int i; + + if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_TYPE3)) { + type = 2; + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_USP)) { + type = 7; + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_DSP)) { + type = 6; + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_ROOT_PORT)) { + type = 5; + } + + /* Only device or port dvsec should exist */ + cxl_dvsec_offset = pcie_find_dvsec(dev, 0x1e98, 0); + if (cxl_dvsec_offset == 0) { + cxl_dvsec_offset = pcie_find_dvsec(dev, 0x1e98, 3); + } + + if (cxl_dvsec_offset) { + cxl_dvsec_len = pci_get_long(dev->config + cxl_dvsec_offset + 4) >> 20; + } + + /* CXL Protocol error record */ + build_append_int_noprefix(table, + (type != 0xff ? 1UL << 0 : 0) | + (1UL << 1) | /* Agent address valid */ + (1UL << 2) | /* Device ID */ + ((sn_cap_offset ? 1UL : 0UL) << 3) | + (1UL << 4) | /* Capability structure */ + ((cxl_dvsec_offset ? 1UL : 0UL) << 5) | + (1UL << 6), /* Error Log */ + 8); + /* Agent Type */ + build_append_int_noprefix(table, type, 1); /* CXL 2.0 device */ + + /* Reserved */ + build_append_int_noprefix(table, 0, 7); + /* Agent Address */ + build_append_int_noprefix(table, PCI_FUNC(dev->devfn), 1); + build_append_int_noprefix(table, PCI_SLOT(dev->devfn), 1); + build_append_int_noprefix(table, pci_dev_bus_num(dev), 1); + build_append_int_noprefix(table, 0 /* Seg */, 2); + /* Reserved */ + build_append_int_noprefix(table, 0, 3); + /* Device id */ + build_append_int_noprefix(table, pci_class->vendor_id, 2); + build_append_int_noprefix(table, pci_class->device_id, 2); + build_append_int_noprefix(table, pci_class->subsystem_vendor_id, 2); + build_append_int_noprefix(table, pci_class->subsystem_id, 2); + build_append_int_noprefix(table, pci_class->class_id, 2); + /* + * TODO: figure out how to get the slot number as the slot number + * capabiltiy is deprecated so it only really exists via _DSM + */ + build_append_int_noprefix(table, 0, 2); + /* Reserved */ + build_append_int_noprefix(table, 0, 4); + + if (sn_cap_offset) { + uint32_t dw = pci_get_long(dev->config + sn_cap_offset + 4); + + build_append_int_noprefix(table, dw, 4); + dw = pci_get_long(dev->config + sn_cap_offset + 8); + build_append_int_noprefix(table, dw, 4); + } else { + build_append_int_noprefix(table, 0, 8); + } + + if (pcie_cap_offset) { + uint32_t *pcie_cap = (uint32_t *)(dev->config + pcie_cap_offset); + for (i = 0; i < 60 / sizeof(uint32_t); i++) { + build_append_int_noprefix(table, pcie_cap[i], sizeof(uint32_t)); + } + } else { /* Odd if we don't have one of these! */ + build_append_int_noprefix(table, 0, 60); + } + + /* CXL DVSEC Length */ + build_append_int_noprefix(table, cxl_dvsec_len, 2); + + /* Error log length */ + build_append_int_noprefix(table, 0x18, 2); /* No head log as I'm lazy */ + /* Reserved */ + build_append_int_noprefix(table, 0, 4); + /* DVSEC */ + for (i = 0; i < cxl_dvsec_len; i += sizeof(uint32_t)) { + uint32_t dw = pci_get_long(dev->config + cxl_dvsec_offset + i); + + build_append_int_noprefix(table, dw, sizeof(dw)); + } + + /* error log */ + if (object_dynamic_cast(OBJECT(dev), TYPE_CXL_TYPE3)) { + CXLType3Dev *ct3d = CXL_TYPE3(dev); + uint32_t *rs = ct3d->cxl_cstate.crb.cache_mem_registers; + + /* + * TODO: Possibly move this to caller to gather up - or work out + * generic way to get to it. + */ + build_append_int_noprefix(table, + ldl_le_p(rs + R_CXL_RAS_UNC_ERR_STATUS), 4); + build_append_int_noprefix(table, + ldl_le_p(rs + R_CXL_RAS_UNC_ERR_MASK), 4); + build_append_int_noprefix(table, + ldl_le_p(rs + R_CXL_RAS_UNC_ERR_SEVERITY), 4); + build_append_int_noprefix(table, + ldl_le_p(rs + R_CXL_RAS_COR_ERR_STATUS), 4); + build_append_int_noprefix(table, + ldl_le_p(rs + R_CXL_RAS_COR_ERR_MASK), 4); + build_append_int_noprefix(table, + ldl_le_p(rs + R_CXL_RAS_ERR_CAP_CTRL), 4); + if (cxl_err) { + for (i = 0; i < CXL_RAS_ERR_HEADER_NUM; i++) { + build_append_int_noprefix(table, cxl_err->header[i], 4); + } + } else { + build_append_int_noprefix(table, 0, 4 * CXL_RAS_ERR_HEADER_NUM); + } + } else { + /* TODO: Add support for ports etc */ + build_append_int_noprefix(table, 0, 0x18 + 512); + } +} + static int acpi_ghes_record_mem_error(uint64_t error_block_address, uint64_t error_physical_addr) { @@ -365,6 +501,52 @@ static int ghes_record_aer_error(PCIDevice *dev, uint64_t error_block_address) return true; } +static int ghes_record_cxl_error(PCIDevice *dev, CXLError *cxl_err, + uint64_t error_block_address) +{ + GArray *block; + uint32_t data_length; + const uint8_t aer_section_id_le[] = { + 0xB4, 0xEF, 0xB9, 0x80, + 0xB5, 0x52, + 0xE3, 0x4D, + 0xA7, 0x77, 0x68, 0x78, 0x4B, 0x77, 0x10, 0x48 }; + QemuUUID fru_id = {0}; + + block = g_array_new(false, true /* clear */, 1); + /* Read the current length in bytes of the generic error data */ + cpu_physical_memory_read(error_block_address + 8, + &data_length, 4); + + /* Add a new generic error data entry */ + data_length += ACPI_GHES_DATA_LENGTH; + /* TO FIX: Error record dependent */ + data_length += ACPI_GHES_PCIE_CPER_LENGTH; + + /* + * Check whether it will run out of the preallocated memory if adding a new + * generic error data entry + */ + if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) { + error_report("Record CPER out of boundary!!!"); + return false; + } + /* Build the new generic error status block header */ + acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE, 0, 0, + data_length, ACPI_CPER_SEV_RECOVERABLE); + + /* Build the new generic error data entry header */ + acpi_ghes_generic_error_data(block, aer_section_id_le, + ACPI_CPER_SEV_RECOVERABLE, 0, 0, + ACPI_GHES_PCIE_CPER_LENGTH, fru_id, 0); + /* Build the CXL CPER */ + build_append_cxl_cper(dev, cxl_err, block); + /* Write back above whole new generic error data entry to guest memory */ + cpu_physical_memory_write(error_block_address, block->data, block->len); + g_array_free(block, true); + return true; +} + /* * Build table for the hardware error fw_cfg blob. * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs. @@ -676,6 +858,36 @@ bool ghes_record_aer_errors(PCIDevice *dev, uint32_t notify) return ghes_record_aer_error(dev, error_block_addr); } +bool ghes_record_cxl_errors(PCIDevice *dev, PCIEAERErr *aer_err, + CXLError *cxl_err, uint32_t notify) +{ + int read_ack_register = 0; + uint64_t read_ack_register_addr = 0; + uint64_t error_block_addr = 0; + + if (!ghes_get_addr(notify, &error_block_addr, &read_ack_register_addr)) { + return false; + } + + cpu_physical_memory_read(read_ack_register_addr, + &read_ack_register, sizeof(uint64_t)); + /* zero means OSPM does not acknowledge the error */ + if (!read_ack_register) { + error_report("Last time OSPM does not acknowledge the error," + " record CPER failed this time, set the ack value to" + " avoid blocking next time CPER record! exit"); + read_ack_register = 1; + cpu_physical_memory_write(read_ack_register_addr, + &read_ack_register, sizeof(uint64_t)); + return false; + } + + read_ack_register = cpu_to_le64(0); + cpu_physical_memory_write(read_ack_register_addr, + &read_ack_register, sizeof(uint64_t)); + return ghes_record_cxl_error(dev, cxl_err, error_block_addr); +} + bool acpi_ghes_present(void) { AcpiGedState *acpi_ged_state; diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index db950d10dc..3a7881118a 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -29,6 +29,8 @@ #include "hw/cxl/cxl.h" #include "hw/pci/msix.h" #include "hw/pci/spdm.h" +#include "hw/boards.h" +#include "hw/acpi/ghes.h" #define DWORD_BYTE 4 #define CXL_CAPACITY_MULTIPLIER (256 * MiB) @@ -1520,6 +1522,8 @@ void qmp_cxl_inject_uncorrectable_errors(const char *path, CXLUncorErrorRecordList *errors, Error **errp) { + MachineState *machine = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(machine); Object *obj = object_resolve_path(path, NULL); static PCIEAERErr err = {}; CXLType3Dev *ct3d; @@ -1605,7 +1609,16 @@ void qmp_cxl_inject_uncorrectable_errors(const char *path, } stl_le_p(reg_state + R_CXL_RAS_UNC_ERR_STATUS, unc_err); - pcie_aer_inject_error(PCI_DEVICE(obj), &err); + if (!acpi_fw_first_pci()) { + pcie_aer_inject_error(PCI_DEVICE(obj), &err); + } else { + ghes_record_cxl_errors(PCI_DEVICE(obj), &err, + QTAILQ_FIRST(&ct3d->error_list), + ACPI_GHES_NOTIFY_GPIO); + if (mc->set_error) { + mc->set_error(); + } + } return; } @@ -1613,6 +1626,8 @@ void qmp_cxl_inject_uncorrectable_errors(const char *path, void qmp_cxl_inject_correctable_error(const char *path, CxlCorErrorType type, Error **errp) { + MachineState *machine = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(machine); static PCIEAERErr err = {}; Object *obj = object_resolve_path(path, NULL); CXLType3Dev *ct3d; @@ -1650,8 +1665,15 @@ void qmp_cxl_inject_correctable_error(const char *path, CxlCorErrorType type, cor_err |= (1 << cxl_err_type); stl_le_p(reg_state + R_CXL_RAS_COR_ERR_STATUS, cor_err); - - pcie_aer_inject_error(PCI_DEVICE(obj), &err); + if (!acpi_fw_first_pci()) { + pcie_aer_inject_error(PCI_DEVICE(obj), &err); + } else { + ghes_record_cxl_errors(PCI_DEVICE(obj), &err, NULL, + ACPI_GHES_NOTIFY_GPIO); + if (mc->set_error) { + mc->set_error(); + } + } } static void cxl_assign_event_header(CXLEventRecordHdr *hdr, diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c index deee8cdb37..15d783913d 100644 --- a/hw/pci-bridge/cxl_root_port.c +++ b/hw/pci-bridge/cxl_root_port.c @@ -54,7 +54,6 @@ typedef struct CXLRootPort { PCIResReserve res_reserve; } CXLRootPort; -#define TYPE_CXL_ROOT_PORT "cxl-rp" DECLARE_INSTANCE_CHECKER(CXLRootPort, CXL_ROOT_PORT, TYPE_CXL_ROOT_PORT) /* From patchwork Mon Feb 5 14:19:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 13545636 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 63126C48295 for ; Mon, 5 Feb 2024 14:25:45 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rWzuU-0001vm-DF; Mon, 05 Feb 2024 09:25:22 -0500 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 1rWzuS-0001ss-JP for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:25:20 -0500 Received: from frasgout.his.huawei.com ([185.176.79.56]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rWzuM-0004Ep-Dy for qemu-devel@nongnu.org; Mon, 05 Feb 2024 09:25:20 -0500 Received: from mail.maildlp.com (unknown [172.18.186.31]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4TT7qV6gndz6D8gC; Mon, 5 Feb 2024 22:21:58 +0800 (CST) Received: from lhrpeml500005.china.huawei.com (unknown [7.191.163.240]) by mail.maildlp.com (Postfix) with ESMTPS id 9ED2C140A36; Mon, 5 Feb 2024 22:25:12 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Mon, 5 Feb 2024 14:25:12 +0000 To: , CC: Igor Mammedov , Ani Sinha , Shannon Zhao , Dongjiu Geng , , "Michael S . Tsirkin" , Ira Weiny , Peter Maydell , Fan Ni , Marcel Apfelbaum Subject: [RFC PATCH 11/11] cxl/type3: Add firmware first error reporting for general media events. Date: Mon, 5 Feb 2024 14:19:40 +0000 Message-ID: <20240205141940.31111-12-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> References: <20240205141940.31111-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500004.china.huawei.com (7.191.163.9) To lhrpeml500005.china.huawei.com (7.191.163.240) Received-SPF: pass client-ip=185.176.79.56; envelope-from=jonathan.cameron@huawei.com; helo=frasgout.his.huawei.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=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: , Reply-to: Jonathan Cameron X-Patchwork-Original-From: Jonathan Cameron via From: Jonathan Cameron Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Initial code for Firmware First injection of general media events. PoC level only - issue to be solved include: * Mapping to CPER error types (recoverable etc). * Some record details are tricky to establish so for now are not provided. Signed-off-by: Jonathan Cameron --- include/hw/acpi/ghes.h | 3 ++ hw/acpi/ghes-stub.c | 6 +++ hw/acpi/ghes.c | 120 +++++++++++++++++++++++++++++++++++++++++ hw/mem/cxl_type3.c | 14 +++-- 4 files changed, 140 insertions(+), 3 deletions(-) diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 3426697ecd..171c3e9dad 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -83,6 +83,9 @@ typedef struct CXLError CXLError; bool ghes_record_cxl_errors(PCIDevice *dev, PCIEAERErr *err, CXLError *cxl_err, uint32_t notify); +typedef struct CXLEventGenMedia CXLEventGenMedia; +bool ghes_record_cxl_event_gm(PCIDevice *dev, + CXLEventGenMedia *gem, uint32_t notify); /** * acpi_ghes_present: Report whether ACPI GHES table is present * diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c index cbc7d57465..34940c6441 100644 --- a/hw/acpi/ghes-stub.c +++ b/hw/acpi/ghes-stub.c @@ -25,6 +25,12 @@ bool ghes_record_cxl_errors(PCIDevice *dev, PCIEAERErr *err, return false; } +bool ghes_record_cxl_event_gm(PCIDevice *dev, CXLEventGenMedia *gen, + uint32_t notify) +{ + return false; +} + bool acpi_ghes_present(void) { return false; diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index c6e863d375..34d8b8a518 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -281,6 +281,49 @@ static void build_append_aer_cper(PCIDevice *dev, GArray *table) } } +static void build_append_cxl_event_cper(PCIDevice *dev, CXLEventGenMedia *gen, + GArray *table) +{ + PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(dev); + uint16_t sn_cap_offset = pcie_find_capability(dev, 0x3); + int i; + + build_append_int_noprefix(table, 0x90, 4); /* Length */ + build_append_int_noprefix(table, + (1UL << 0) | /* Device ID */ + ((sn_cap_offset ? 1UL : 0UL) << 1) | + (1UL << 2), /* Event Log entry */ + 8); + /* Device id - differnet syntax from protocol error - sigh */ + build_append_int_noprefix(table, pci_class->vendor_id, 2); + build_append_int_noprefix(table, pci_class->device_id, 2); + build_append_int_noprefix(table, PCI_FUNC(dev->devfn), 1); + build_append_int_noprefix(table, PCI_SLOT(dev->devfn), 1); + build_append_int_noprefix(table, pci_dev_bus_num(dev), 1); + build_append_int_noprefix(table, 0 /* Seg */, 2); + /* + * TODO: figure out how to get the slot number as the slot number + * capabiltiy is deprecated so it only really exists via _DSM + */ + build_append_int_noprefix(table, 0, 2); + + /* Reserved */ + build_append_int_noprefix(table, 0, 1); + + if (sn_cap_offset) { + uint32_t dw = pci_get_long(dev->config + sn_cap_offset + 4); + + build_append_int_noprefix(table, dw, 4); + dw = pci_get_long(dev->config + sn_cap_offset + 8); + build_append_int_noprefix(table, dw, 4); + } else { + build_append_int_noprefix(table, 0, 8); + } + for (i = offsetof(typeof(*gen), hdr.length); i < sizeof(*gen); i++) { + build_append_int_noprefix(table, ((uint8_t *)gen)[i], 1); + } +} + static void build_append_cxl_cper(PCIDevice *dev, CXLError *cxl_err, GArray *table) { @@ -501,6 +544,52 @@ static int ghes_record_aer_error(PCIDevice *dev, uint64_t error_block_address) return true; } +static int ghes_record_cxl_gen_media(PCIDevice *dev, CXLEventGenMedia *gem, + uint64_t error_block_address) +{ + QemuUUID fru_id = {0}; + GArray *block; + uint32_t data_length; + uint32_t event_length = 0x90; + const uint8_t section_id_le[] = { 0x77, 0x0a, 0xcd, 0xfb, + 0x60, 0xc2, + 0x7f, 0x41, + 0x85, 0xa9, + 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6 }; + block = g_array_new(false, true, 1); + /* Read the current length in bytes of the generic error data */ + cpu_physical_memory_read(error_block_address + 8, &data_length, 4); + + /* Add a new generic error data entry*/ + data_length += ACPI_GHES_DATA_LENGTH; + data_length += event_length; + + /* + * Check whether it will run out of the preallocated memory if adding a new + * generic error data entry + */ + if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) { + error_report("Record CPER out of boundary!!!"); + return false; + } + /* Build the new generic error status block header */ + acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE, 0, 0, + data_length, ACPI_CPER_SEV_RECOVERABLE); + + /* Build the new generic error data entry header */ + acpi_ghes_generic_error_data(block, section_id_le, + ACPI_CPER_SEV_RECOVERABLE, 0, 0, + 0x90, fru_id, 0); + + /* Build the CXL CPER */ + build_append_cxl_event_cper(dev, gem, block); /* 0x90 long */ + /* Write back above whole new generic error data entry to guest memory */ + cpu_physical_memory_write(error_block_address, block->data, block->len); + g_array_free(block, true); + + return 0; +} + static int ghes_record_cxl_error(PCIDevice *dev, CXLError *cxl_err, uint64_t error_block_address) { @@ -858,6 +947,37 @@ bool ghes_record_aer_errors(PCIDevice *dev, uint32_t notify) return ghes_record_aer_error(dev, error_block_addr); } +bool ghes_record_cxl_event_gm(PCIDevice *dev, CXLEventGenMedia *gem, + uint32_t notify) +{ + int read_ack_register = 0; + uint64_t read_ack_register_addr = 0; + uint64_t error_block_addr = 0; + + if (!ghes_get_addr(notify, &error_block_addr, &read_ack_register_addr)) { + return false; + } + + cpu_physical_memory_read(read_ack_register_addr, + &read_ack_register, sizeof(uint64_t)); + /* zero means OSPM does not acknowledge the error */ + if (!read_ack_register) { + error_report("Last time OSPM does not acknowledge the error," + " record CPER failed this time, set the ack value to" + " avoid blocking next time CPER record! exit"); + read_ack_register = 1; + cpu_physical_memory_write(read_ack_register_addr, + &read_ack_register, sizeof(uint64_t)); + return false; + } + + read_ack_register = cpu_to_le64(0); + cpu_physical_memory_write(read_ack_register_addr, + &read_ack_register, sizeof(uint64_t)); + + return ghes_record_cxl_gen_media(dev, gem, error_block_addr); +} + bool ghes_record_cxl_errors(PCIDevice *dev, PCIEAERErr *aer_err, CXLError *cxl_err, uint32_t notify) { diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 3a7881118a..1cc58293a2 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -1734,6 +1734,8 @@ void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log, const char *component_id, Error **errp) { + MachineState *machine = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(machine); Object *obj = object_resolve_path(path, NULL); CXLEventGenMedia gem; CXLEventRecordHdr *hdr = &gem.hdr; @@ -1792,9 +1794,15 @@ void qmp_cxl_inject_general_media_event(const char *path, CxlEventLog log, } stw_le_p(&gem.validity_flags, valid_flags); - - if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&gem)) { - cxl_event_irq_assert(ct3d); + if (!acpi_fw_first_pci()) { + if (cxl_event_insert(cxlds, enc_log, (CXLEventRecordRaw *)&gem)) { + cxl_event_irq_assert(ct3d); + } + } else { + ghes_record_cxl_event_gm(PCI_DEVICE(ct3d), &gem, ACPI_GHES_NOTIFY_GPIO); + if (mc->set_error) { + mc->set_error(); + } } }