From patchwork Thu Aug 1 14:47:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 13750604 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 923D4C3DA64 for ; Thu, 1 Aug 2024 14:48:31 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sZX5P-0000zZ-VS; Thu, 01 Aug 2024 10:47:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5N-0000vD-GS; Thu, 01 Aug 2024 10:47:21 -0400 Received: from dfw.source.kernel.org ([2604:1380:4641:c500::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5L-0001qW-Pk; Thu, 01 Aug 2024 10:47:21 -0400 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id F06A46288B; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9E211C4AF0F; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1722523637; bh=wmX5BOavDV5A0y4JGTIfwXXXDCYeYux2q4KKf6xw9vs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XEiVgpxRD5QuvI2aa7eSeynvkq9I/k9VUg7fXPfxYcnSAT6CBRMyz3bNwuEATzv9Z cpdb/WkMG9CvS7af3RiJRP7aNAHw6i3TkOwS3LL9EboTKkOrg0j2qXq8uhzuw4qGWv uoVX1iW3cQckjEyjBOh5C5SvJIBuJK1nnj6pDzU3K0q0cH0Y+ltEcJmlNiQqhTdR2p G0CPpxya5vTC+9Cce0C9J9O4F2tyoSN1cIcAUEOCFCPFWUGDsYJXH/yrxB5Uz1wQlD fA1X/oAA9KC5284Eya4YzLoDvowI4ZKDW+ky3vnc/GmlkrkpfbOPAudbJjALTMTRfx sGXUdrNcI981A== Received: from mchehab by mail.kernel.org with local (Exim 4.98) (envelope-from ) id 1sZX5H-00000001WCT-2os4; Thu, 01 Aug 2024 16:47:15 +0200 From: Mauro Carvalho Chehab To: Cc: Jonathan Cameron , Shiju Jose , Mauro Carvalho Chehab , "Michael S. Tsirkin" , Ani Sinha , Igor Mammedov , Peter Maydell , Shannon Zhao , linux-kernel@vger.kernel.org, qemu-arm@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 1/7] arm/virt: place power button pin number on a define Date: Thu, 1 Aug 2024 16:47:04 +0200 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2604:1380:4641:c500::1; envelope-from=mchehab+huawei@kernel.org; helo=dfw.source.kernel.org X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.131, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Having magic numbers inside the code is not a good idea, as it is error-prone. So, instead, create a macro with the number definition. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Jonathan Cameron --- hw/arm/virt-acpi-build.c | 6 +++--- hw/arm/virt.c | 7 ++++--- include/hw/arm/virt.h | 3 +++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index e10cad86dd73..f76fb117adff 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -154,10 +154,10 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, aml_append(dev, aml_name_decl("_CRS", crs)); Aml *aei = aml_resource_template(); - /* Pin 3 for power button */ - const uint32_t pin_list[1] = {3}; + + const uint32_t pin = GPIO_PIN_POWER_BUTTON; 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)); aml_append(dev, aml_name_decl("_AEI", aei)); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 719e83e6a1e7..687fe0bb8bc9 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1004,7 +1004,7 @@ static void virt_powerdown_req(Notifier *n, void *opaque) if (s->acpi_dev) { acpi_send_event(s->acpi_dev, ACPI_POWER_DOWN_STATUS); } else { - /* use gpio Pin 3 for power button event */ + /* use gpio Pin for power button event */ qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); } } @@ -1013,7 +1013,8 @@ static void create_gpio_keys(char *fdt, DeviceState *pl061_dev, uint32_t phandle) { gpio_key_dev = sysbus_create_simple("gpio-key", -1, - qdev_get_gpio_in(pl061_dev, 3)); + qdev_get_gpio_in(pl061_dev, + GPIO_PIN_POWER_BUTTON)); qemu_fdt_add_subnode(fdt, "/gpio-keys"); qemu_fdt_setprop_string(fdt, "/gpio-keys", "compatible", "gpio-keys"); @@ -1024,7 +1025,7 @@ static void create_gpio_keys(char *fdt, DeviceState *pl061_dev, qemu_fdt_setprop_cell(fdt, "/gpio-keys/poweroff", "linux,code", KEY_POWER); qemu_fdt_setprop_cells(fdt, "/gpio-keys/poweroff", - "gpios", phandle, 3, 0); + "gpios", phandle, GPIO_PIN_POWER_BUTTON, 0); } #define SECURE_GPIO_POWEROFF 0 diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index ab961bb6a9b8..a4d937ed45ac 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -47,6 +47,9 @@ /* See Linux kernel arch/arm64/include/asm/pvclock-abi.h */ #define PVTIME_SIZE_PER_CPU 64 +/* GPIO pins */ +#define GPIO_PIN_POWER_BUTTON 3 + enum { VIRT_FLASH, VIRT_MEM, From patchwork Thu Aug 1 14:47:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 13750605 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 09E56C3DA4A for ; Thu, 1 Aug 2024 14:48:52 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sZX5T-0001GD-ML; Thu, 01 Aug 2024 10:47:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5R-00014X-3f for qemu-devel@nongnu.org; Thu, 01 Aug 2024 10:47:25 -0400 Received: from sin.source.kernel.org ([145.40.73.55]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5O-0001qt-P4 for qemu-devel@nongnu.org; Thu, 01 Aug 2024 10:47:24 -0400 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id 7A9BCCE19CF; Thu, 1 Aug 2024 14:47:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A0BBBC4AF10; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1722523637; bh=lzZeLSx62/9+XmtaXqmWuty+3/8CulkJ9V68HTTwfN0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sPCMjIXcb2OwUJTYSb60jP8op6LR36GR1okXTfhng4gUs8WsQ6JT0WSFtDrnC2Lgu bmPfWnVwCSgthLK1wlUwqbr86FwGxw5Rb2gIE8t9OfDTrH9TkpnGmWzU4ASW58HM6q zQnJkwRamVFeKa5OLJ1FflMnnjQwrVqDqlpYxZ4H2BO3QofouyOiwbm6kOgZOZyqO2 4wPMXay83InlmgxUAdOg3CGCD22X2Rd7yzFDYZGwDSmm6QnfUuYFWnmRPpEiAFWAJA 1hKV7JZLB1yRx/sE2yFFZCnD3R0CCOv/aQDMoeo2PDFp5cm4tKcETQUjJp7LTMaF+H G3/R4RWy6wwgw== Received: from mchehab by mail.kernel.org with local (Exim 4.98) (envelope-from ) id 1sZX5H-00000001WCW-2vaH; Thu, 01 Aug 2024 16:47:15 +0200 From: Mauro Carvalho Chehab To: Cc: Jonathan Cameron , Shiju Jose , Mauro Carvalho Chehab , "Michael S. Tsirkin" , Ani Sinha , Igor Mammedov , linux-kernel@vger.kernel.org, qemu-devel@nongnu.org Subject: [PATCH v4 2/7] acpi/generic_event_device: add an APEI error device Date: Thu, 1 Aug 2024 16:47:05 +0200 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=145.40.73.55; envelope-from=mchehab+huawei@kernel.org; helo=sin.source.kernel.org X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.131, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Adds a Generic Event Device to handle generic hardware error events, supporting General Purpose Event (GPE) as specified at ACPI 6.5 specification at 18.3.2.7.2: https://uefi.org/specs/ACPI/6.5/18_Platform_Error_Interfaces.html#event-notification-for-generic-error-sources using HID PNP0C33. The PNP0C33 device is used to report hardware errors to the bios via ACPI APEI Generic Hardware Error Source (GHES). Co-authored-by: Mauro Carvalho Chehab Co-authored-by: Jonathan Cameron Cc: Jonathan Cameron Signed-off-by: Mauro Carvalho Chehab --- hw/acpi/generic_event_device.c | 17 +++++++++++++++++ include/hw/acpi/acpi_dev_interface.h | 1 + include/hw/acpi/generic_event_device.h | 3 +++ 3 files changed, 21 insertions(+) diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index 15b4c3ebbf24..b9ad05e98c05 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -26,6 +26,7 @@ static const uint32_t ged_supported_events[] = { ACPI_GED_PWR_DOWN_EVT, ACPI_GED_NVDIMM_HOTPLUG_EVT, ACPI_GED_CPU_HOTPLUG_EVT, + ACPI_GED_ERROR_EVT }; /* @@ -116,6 +117,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), aml_int(0x80))); break; + case ACPI_GED_ERROR_EVT: + aml_append(if_ctx, + aml_notify(aml_name(ACPI_APEI_ERROR_DEVICE), + aml_int(0x80))); + break; case ACPI_GED_NVDIMM_HOTPLUG_EVT: aml_append(if_ctx, aml_notify(aml_name("\\_SB.NVDR"), @@ -153,6 +159,15 @@ void acpi_dsdt_add_power_button(Aml *scope) aml_append(scope, dev); } +void acpi_dsdt_add_error_device(Aml *scope) +{ + Aml *dev = aml_device(ACPI_APEI_ERROR_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); +} + /* Memory read by the GED _EVT AML dynamic method */ static uint64_t ged_evt_read(void *opaque, hwaddr addr, unsigned size) { @@ -295,6 +310,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) sel = ACPI_GED_MEM_HOTPLUG_EVT; } else if (ev & ACPI_POWER_DOWN_STATUS) { sel = ACPI_GED_PWR_DOWN_EVT; + } else if (ev & ACPI_GENERIC_ERROR) { + sel = ACPI_GED_ERROR_EVT; } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) { sel = ACPI_GED_NVDIMM_HOTPLUG_EVT; } else if (ev & ACPI_CPU_HOTPLUG_STATUS) { diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h index 68d9d15f50aa..8294f8f0ccca 100644 --- a/include/hw/acpi/acpi_dev_interface.h +++ b/include/hw/acpi/acpi_dev_interface.h @@ -13,6 +13,7 @@ typedef enum { ACPI_NVDIMM_HOTPLUG_STATUS = 16, ACPI_VMGENID_CHANGE_STATUS = 32, ACPI_POWER_DOWN_STATUS = 64, + ACPI_GENERIC_ERROR = 128, } AcpiEventStatusBits; #define TYPE_ACPI_DEVICE_IF "acpi-device-interface" diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index 40af3550b56d..b8f2f1328e0c 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -66,6 +66,7 @@ #include "qom/object.h" #define ACPI_POWER_BUTTON_DEVICE "PWRB" +#define ACPI_APEI_ERROR_DEVICE "GEDD" #define TYPE_ACPI_GED "acpi-ged" OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) @@ -98,6 +99,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) #define ACPI_GED_PWR_DOWN_EVT 0x2 #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 #define ACPI_GED_CPU_HOTPLUG_EVT 0x8 +#define ACPI_GED_ERROR_EVT 0x10 typedef struct GEDState { MemoryRegion evt; @@ -120,5 +122,6 @@ struct AcpiGedState { void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); void acpi_dsdt_add_power_button(Aml *scope); +void acpi_dsdt_add_error_device(Aml *scope); #endif From patchwork Thu Aug 1 14:47:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 13750603 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 86850C3DA64 for ; Thu, 1 Aug 2024 14:48:27 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sZX5R-000171-N4; Thu, 01 Aug 2024 10:47:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5P-0000xT-Dk; Thu, 01 Aug 2024 10:47:23 -0400 Received: from dfw.source.kernel.org ([139.178.84.217]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5L-0001qc-Si; Thu, 01 Aug 2024 10:47:23 -0400 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 916B5628E2; Thu, 1 Aug 2024 14:47:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 98B82C4AF0A; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1722523637; bh=rzo7GJ37SsXEzwNYx2lTpLxCPLuIqxbfFLqogTN1q0I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RSrEZGAX5YKi3zi0HAIJjqeM1Z7Khuttolv7Jr4WvlWNpsbAzRIgEGH+eK3sRxPLa ge9K0LmDqGJikLiHJ8KPb4QJJFlhwcgXT3JTpr3lWaJ987NAdHdDrGLgIyNRs3PMAV eqpnexjA18ou56zk0P3MN3T47XqVx2Uml4mfs4PVQVQL8FpFtdntBpqdFodNt8Dra2 da8dboPSG4qJU/LdVaS+ZCsG8GXWRBNTeCCgsprBx+/eqbt4sJVixTEvBwdk+XNqVZ lAFNnDWf93Hwf+ksDi/4DerXOOzQWhB2D7krg+DWgG3mkFEMWj18Q59EISmCjhFf1V Ufyp/s6kIeQGw== Received: from mchehab by mail.kernel.org with local (Exim 4.98) (envelope-from ) id 1sZX5H-00000001WCZ-32Su; Thu, 01 Aug 2024 16:47:15 +0200 From: Mauro Carvalho Chehab To: Cc: Jonathan Cameron , Shiju Jose , Mauro Carvalho Chehab , "Michael S. Tsirkin" , Ani Sinha , Dongjiu Geng , Igor Mammedov , Peter Maydell , Shannon Zhao , linux-kernel@vger.kernel.org, qemu-arm@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 3/7] arm/virt: Wire up GPIO error source for ACPI / GHES Date: Thu, 1 Aug 2024 16:47:06 +0200 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=139.178.84.217; envelope-from=mchehab+huawei@kernel.org; helo=dfw.source.kernel.org X-Spam_score_int: -71 X-Spam_score: -7.2 X-Spam_bar: ------- X-Spam_report: (-7.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.131, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Adds support to ARM virtualization to allow handling a General Purpose Event (GPE) via GED error device. It is aligned with Linux Kernel patch: https://lore.kernel.org/lkml/1272350481-27951-8-git-send-email-ying.huang@intel.com/ Co-authored-by: Mauro Carvalho Chehab Co-authored-by: Jonathan Cameron Cc: Jonathan Cameron Signed-off-by: Mauro Carvalho Chehab --- hw/acpi/ghes.c | 3 +++ hw/arm/virt-acpi-build.c | 21 +++++++++++++++++---- hw/arm/virt.c | 26 +++++++++++++++++++++++--- include/hw/acpi/ghes.h | 3 +++ include/hw/arm/virt.h | 2 ++ 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index e9511d9b8f71..8d0262e6c1aa 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -444,6 +444,9 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) return ret; } +NotifierList generic_error_notifiers = + NOTIFIER_LIST_INITIALIZER(error_device_notifiers); + bool acpi_ghes_present(void) { AcpiGedState *acpi_ged_state; diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index f76fb117adff..cdd1c6d9f1a3 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -142,6 +142,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, uint32_t gpio_irq) { + uint32_t pin; + Aml *dev = aml_device("GPO0"); aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0061"))); aml_append(dev, aml_name_decl("_UID", aml_int(0))); @@ -155,7 +157,12 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, Aml *aei = aml_resource_template(); - const uint32_t pin = GPIO_PIN_POWER_BUTTON; + pin = GPIO_PIN_POWER_BUTTON; + aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, AML_PULL_UP, 0, &pin, 1, + "GPO0", NULL, 0)); + + pin = GPIO_PIN_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)); @@ -166,6 +173,12 @@ 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_APEI_ERROR_DEVICE), + aml_int(0x80))); + aml_append(dev, method); + aml_append(scope, dev); } @@ -841,10 +854,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) HOTPLUG_HANDLER(vms->acpi_dev), 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), @@ -858,6 +870,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) } acpi_dsdt_add_power_button(scope); + acpi_dsdt_add_error_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 687fe0bb8bc9..e76cc9690788 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -73,6 +73,7 @@ #include "standard-headers/linux/input.h" #include "hw/arm/smmuv3.h" #include "hw/acpi/acpi.h" +#include "hw/acpi/ghes.h" #include "target/arm/cpu-qom.h" #include "target/arm/internals.h" #include "target/arm/multiprocessing.h" @@ -677,7 +678,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) DeviceState *dev; MachineState *ms = MACHINE(vms); int irq = vms->irqmap[VIRT_ACPI_GED]; - uint32_t event = ACPI_GED_PWR_DOWN_EVT; + uint32_t event = ACPI_GED_PWR_DOWN_EVT | ACPI_GED_ERROR_EVT; if (ms->ram_slots) { event |= ACPI_GED_MEM_HOTPLUG_EVT; @@ -1009,12 +1010,28 @@ static void virt_powerdown_req(Notifier *n, void *opaque) } } +static DeviceState *gpio_error_dev; +static void virt_generic_error_req(Notifier *n, void *opaque) +{ + VirtMachineState *s = container_of(n, VirtMachineState, generic_error_notifier); + + if (s->acpi_dev) { + acpi_send_event(s->acpi_dev, ACPI_GENERIC_ERROR); + } else { + /* use gpio Pin for power button event */ + qemu_set_irq(qdev_get_gpio_in(gpio_error_dev, 0), 1); + } +} + static void create_gpio_keys(char *fdt, DeviceState *pl061_dev, uint32_t phandle) { gpio_key_dev = sysbus_create_simple("gpio-key", -1, qdev_get_gpio_in(pl061_dev, GPIO_PIN_POWER_BUTTON)); + gpio_error_dev = sysbus_create_simple("gpio-key", -1, + qdev_get_gpio_in(pl061_dev, + GPIO_PIN_GENERIC_ERROR)); qemu_fdt_add_subnode(fdt, "/gpio-keys"); qemu_fdt_setprop_string(fdt, "/gpio-keys", "compatible", "gpio-keys"); @@ -2385,9 +2402,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); @@ -2397,6 +2413,10 @@ static void machvirt_init(MachineState *machine) vms->powerdown_notifier.notify = virt_powerdown_req; qemu_register_powerdown_notifier(&vms->powerdown_notifier); + vms->generic_error_notifier.notify = virt_generic_error_req; + notifier_list_add(&generic_error_notifiers, + &vms->generic_error_notifier); + /* Create mmio transports, so the user can create virtio backends * (which will be automatically plugged in to the transports). If * no backend is created the transport will just sit harmlessly idle. diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 674f6958e905..6891eafff5ab 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -23,6 +23,9 @@ #define ACPI_GHES_H #include "hw/acpi/bios-linker-loader.h" +#include "qemu/notify.h" + +extern NotifierList generic_error_notifiers; /* * Values for Hardware Error Notification Type field diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index a4d937ed45ac..0cbe9a05605f 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -49,6 +49,7 @@ /* GPIO pins */ #define GPIO_PIN_POWER_BUTTON 3 +#define GPIO_PIN_GENERIC_ERROR 6 enum { VIRT_FLASH, @@ -175,6 +176,7 @@ struct VirtMachineState { DeviceState *gic; DeviceState *acpi_dev; Notifier powerdown_notifier; + Notifier generic_error_notifier; PCIBus *bus; char *oem_id; char *oem_table_id; From patchwork Thu Aug 1 14:47:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 13750602 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 0E43EC3DA64 for ; Thu, 1 Aug 2024 14:48:20 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sZX5S-00019i-CP; Thu, 01 Aug 2024 10:47:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5Q-00012j-LI; Thu, 01 Aug 2024 10:47:24 -0400 Received: from sin.source.kernel.org ([145.40.73.55]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5O-0001qu-En; Thu, 01 Aug 2024 10:47:24 -0400 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id 7A9AACE19AC; Thu, 1 Aug 2024 14:47:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A744C4AF0E; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1722523637; bh=ZSlU9yW3n4NevgGhDHVq1qOszSSTbSe+VJ0pqN5i5yU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b8yFjYE76/sFm9kbAue+HHob2c5rr4BMxKxJvju+zUE1QBo8L+DDi7BoYg+rNASaT oWxANK4T34KKSGddhezbOdMgwXehm+CALhcwnqYICwXTCFpHb3g4ySoWN3mydHZPLD Mp61xPxdczn0BbCZByv8O1VimxSsUTlhs7hwogRPgWaxnyK7eeGZsGahVW5XEXl3Qd b+shdSCgtkCXFMlDAX2GWUz+ZTPPzdtnKT8QDAYxDd8CZsWHRTeqmTnL652yI+JNq2 65IUwJg5ST6bDvCVyhVm2LEClX64Q3PdfVydMmcrnE7ZYygriL6/m4DqsO7U3bSp9z h91yk9X3NcWlA== Received: from mchehab by mail.kernel.org with local (Exim 4.98) (envelope-from ) id 1sZX5H-00000001WCf-398k; Thu, 01 Aug 2024 16:47:15 +0200 From: Mauro Carvalho Chehab To: Cc: Jonathan Cameron , Shiju Jose , "Michael S. Tsirkin" , Ani Sinha , Dongjiu Geng , Igor Mammedov , linux-kernel@vger.kernel.org, qemu-arm@nongnu.org, qemu-devel@nongnu.org, Mauro Carvalho Chehab Subject: [PATCH v4 4/7] acpi/ghes: Support GPIO error source Date: Thu, 1 Aug 2024 16:47:07 +0200 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=145.40.73.55; envelope-from=mchehab+huawei@kernel.org; helo=sin.source.kernel.org X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.131, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Jonathan Cameron Add error notification to GHES v2 using the GPIO source. [mchehab: do some cleanups at ACPI_HEST_SRC_ID_* checks] Signed-off-by: Jonathan Cameron Signed-off-by: Mauro Carvalho Chehab --- hw/acpi/ghes.c | 16 ++++++++++------ include/hw/acpi/ghes.h | 3 ++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index 8d0262e6c1aa..a745dcc7be5e 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 @@ -290,6 +290,9 @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker) static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker) { uint64_t address_offset; + + assert(source_id < ACPI_HEST_SRC_ID_RESERVED); + /* * Type: * Generic Hardware Error Source version 2(GHESv2 - Type 10) @@ -327,6 +330,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 +376,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); } @@ -406,10 +413,7 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address) start_addr = le64_to_cpu(ags->ghes_addr_le); if (physical_address) { - - if (source_id < ACPI_HEST_SRC_ID_RESERVED) { - start_addr += source_id * sizeof(uint64_t); - } + start_addr += source_id * sizeof(uint64_t); cpu_physical_memory_read(start_addr, &error_block_addr, sizeof(error_block_addr)); diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 6891eafff5ab..33be1eb5acf4 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -59,9 +59,10 @@ enum AcpiGhesNotifyType { ACPI_GHES_NOTIFY_RESERVED = 12 }; +/* Those are used as table indexes when building GHES tables */ enum { ACPI_HEST_SRC_ID_SEA = 0, - /* future ids go here */ + ACPI_HEST_SRC_ID_GPIO, ACPI_HEST_SRC_ID_RESERVED, }; From patchwork Thu Aug 1 14:47:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 13750607 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 09863C3DA64 for ; Thu, 1 Aug 2024 14:49:09 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sZX5R-00015K-Al; Thu, 01 Aug 2024 10:47:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5P-0000xQ-9v; Thu, 01 Aug 2024 10:47:23 -0400 Received: from dfw.source.kernel.org ([2604:1380:4641:c500::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5L-0001qX-QT; Thu, 01 Aug 2024 10:47:23 -0400 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 445C362381; Thu, 1 Aug 2024 14:47:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A673DC4AF12; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1722523637; bh=inI4stFbv14+sS7oa5RIwxj/FX+TvJx1kVyZnVYHKuQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Si/dw9s7gbhmlNguqCDcHfrC1uhpkaOK49d1rpKo5guVajK1i39WlYhSSIi7JJp89 eDL9UdjAD0pEcgn+hokuXtdBVaIqHSdey/ODL8bwB0tJAO5j2w3PWz+/lcQhu/RMh2 R4O3WkOJUdFyGTVxVOKdYHQLX0/qKIslVfq5uysQ7boyyJs5pKUFpqYD/mgd8t88A+ vbWYCnSPAyrjRyLZCHoRSKkvj45wu+UsPOIKjuYlEgn+0xaGo1R46ppCQwpTpLlnDu jAGa0MpWUdoARAzi4h2Z1Lrgy9YWXoN6aBfcFwuMx4XtPYF960eHduRU5nV1k/kRCY /bV+vo3iOhIUA== Received: from mchehab by mail.kernel.org with local (Exim 4.98) (envelope-from ) id 1sZX5H-00000001WCj-3Fzx; Thu, 01 Aug 2024 16:47:15 +0200 From: Mauro Carvalho Chehab To: Cc: Jonathan Cameron , Shiju Jose , Mauro Carvalho Chehab , "Michael S. Tsirkin" , Ani Sinha , Dongjiu Geng , Eric Blake , Igor Mammedov , Markus Armbruster , Michael Roth , Paolo Bonzini , Peter Maydell , linux-kernel@vger.kernel.org, qemu-arm@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 5/7] qapi/ghes-cper: add an interface to do generic CPER error injection Date: Thu, 1 Aug 2024 16:47:08 +0200 Message-ID: <5a4da771f04beea4e7488eee8080c0ace372e9a0.1722523312.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2604:1380:4641:c500::1; envelope-from=mchehab+huawei@kernel.org; helo=dfw.source.kernel.org X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.131, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Creates a QAPI to be used for generic ACPI APEI hardware error injection (HEST) via GHESv2. The actual GHES code will be added at the followup patch. Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 7 ++++++ hw/acpi/Kconfig | 5 ++++ hw/acpi/ghes_cper.c | 53 +++++++++++++++++++++++++++++++++++++++++ hw/acpi/meson.build | 2 ++ hw/arm/Kconfig | 5 ++++ include/hw/acpi/ghes.h | 6 +++++ qapi/ghes-cper.json | 54 ++++++++++++++++++++++++++++++++++++++++++ qapi/meson.build | 1 + qapi/qapi-schema.json | 1 + 9 files changed, 134 insertions(+) create mode 100644 hw/acpi/ghes_cper.c create mode 100644 qapi/ghes-cper.json diff --git a/MAINTAINERS b/MAINTAINERS index 98eddf7ae155..655edcb6688c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2075,6 +2075,13 @@ F: hw/acpi/ghes.c F: include/hw/acpi/ghes.h F: docs/specs/acpi_hest_ghes.rst +ACPI/HEST/GHES/ARM processor CPER +R: Mauro Carvalho Chehab +S: Maintained +F: hw/arm/ghes_cper.c +F: hw/acpi/ghes_cper_stub.c +F: qapi/ghes-cper.json + ppc4xx L: qemu-ppc@nongnu.org S: Orphan diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig index e07d3204eb36..73ffbb82c150 100644 --- a/hw/acpi/Kconfig +++ b/hw/acpi/Kconfig @@ -51,6 +51,11 @@ config ACPI_APEI bool depends on ACPI +config GHES_CPER + bool + depends on ACPI_APEI + default y + config ACPI_PCI bool depends on ACPI && PCI diff --git a/hw/acpi/ghes_cper.c b/hw/acpi/ghes_cper.c new file mode 100644 index 000000000000..0d32874a84f1 --- /dev/null +++ b/hw/acpi/ghes_cper.c @@ -0,0 +1,53 @@ +/* + * ARM Processor error injection + * + * Copyright(C) 2024 Huawei LTD. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-ghes-cper.h" +#include "hw/acpi/ghes.h" + +void qmp_ghes_cper(CommonPlatformErrorRecord *qmp_cper, + Error **errp) +{ + unsigned int uuid_len = 0, i; + uint8List *p; + AcpiGhesCper cper; + + for (p = qmp_cper->notification_type; p; p = p->next) { + uuid_len++; + if (uuid_len > 16) { + break; + } + cper.uuid[uuid_len - 1] = p->value; + } + + if (uuid_len != 16) { + error_report("GHES CPER record has an invalid UUID size"); + return; + } + + cper.data_len = 0; + + for (p = qmp_cper->raw_data; p; p = p->next) { + cper.data_len++; + } + + cper.data = g_malloc(cper.data_len); + + p = qmp_cper->raw_data; + for (i = 0; i < cper.data_len; i++, p = p->next) { + cper.data[i] = p->value; + } + + /* TODO: call a function at ghes */ + + g_free(cper.data); +} diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build index fa5c07db9068..6cbf430eb66d 100644 --- a/hw/acpi/meson.build +++ b/hw/acpi/meson.build @@ -34,4 +34,6 @@ endif system_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c', 'acpi_interface.c')) system_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_false: files('pci-bridge-stub.c')) system_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss) +system_ss.add(when: 'CONFIG_GHES_CPER', if_true: files('ghes_cper.c')) +system_ss.add(when: 'CONFIG_GHES_CPER', if_false: files('ghes_cper_stub.c')) system_ss.add(files('acpi-qmp-cmds.c')) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 1ad60da7aa2d..bed6ba27d715 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -712,3 +712,8 @@ config ARMSSE select UNIMP select SSE_COUNTER select SSE_TIMER + +config GHES_CPER + bool + depends on ARM + default y if AARCH64 diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 33be1eb5acf4..02ea3715f655 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -78,6 +78,12 @@ 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 AcpiGhesCper { + uint8_t uuid[16]; + char *data; + uint32_t data_len; +} AcpiGhesCper; + /** * acpi_ghes_present: Report whether ACPI GHES table is present * diff --git a/qapi/ghes-cper.json b/qapi/ghes-cper.json new file mode 100644 index 000000000000..2b0438431054 --- /dev/null +++ b/qapi/ghes-cper.json @@ -0,0 +1,54 @@ +# -*- Mode: Python -*- +# vim: filetype=python + +## +# = GHESv2 CPER Error Injection +# +# These are defined at +# ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2 +# (GHESv2 - Type 10) +## + +## +# @CommonPlatformErrorRecord: +# +# Common Platform Error Record - CPER - as defined at the UEFI +# specification. See +# https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header +# for more details. +# +# @notification-type: pre-assigned GUID value indicating the record +# association with an error event notification type, as defined +# at https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header +# +# @raw-data: Contains the payload of the CPER. +# +# Since: 9.2 +## +{ 'struct': 'CommonPlatformErrorRecord', + 'data': { + 'notification-type': ['uint8'], + 'raw-data': ['uint8'] + } +} + +## +# @ghes-cper: +# +# Inject ARM Processor error with data to be filled according with +# ACPI 6.2 GHESv2 spec. +# +# @cper: a single CPER record to be sent to the guest OS. +# +# Features: +# +# @unstable: This command is experimental. +# +# Since: 9.2 +## +{ 'command': 'ghes-cper', + 'data': { + 'cper': 'CommonPlatformErrorRecord' + }, + 'features': [ 'unstable' ] +} diff --git a/qapi/meson.build b/qapi/meson.build index e7bc54e5d047..bd13cd7d40c9 100644 --- a/qapi/meson.build +++ b/qapi/meson.build @@ -35,6 +35,7 @@ qapi_all_modules = [ 'dump', 'ebpf', 'error', + 'ghes-cper', 'introspect', 'job', 'machine-common', diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index b1581988e4eb..54165c8d6655 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -81,3 +81,4 @@ { 'include': 'vfio.json' } { 'include': 'cryptodev.json' } { 'include': 'cxl.json' } +{ 'include': 'ghes-cper.json' } From patchwork Thu Aug 1 14:47:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 13750606 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 69592C3DA4A for ; Thu, 1 Aug 2024 14:49:07 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sZX5T-0001FW-HC; Thu, 01 Aug 2024 10:47:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5R-00016L-G4; Thu, 01 Aug 2024 10:47:25 -0400 Received: from sin.source.kernel.org ([2604:1380:40e1:4800::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5O-0001r4-WB; Thu, 01 Aug 2024 10:47:25 -0400 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id C0679CE1928; Thu, 1 Aug 2024 14:47:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 950D2C4AF09; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1722523637; bh=5vVNmeoIiLhqMUtCAtu3KNbQH6/d3NxIciD+hVX1/nw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eRSBm+NAXOrW9hy/RU2Ph9A51tXaCswQEYzguoqvdTJQ2MhrkAXvc2ZTKxUz00/mQ SMqJtsNw11FpnALX4FgRTXHXNk97s0RJRqsEgB/VS3pazRCVxSmn9p/IK72ubXAqkn 7WZlm7XPzJ/HKeY3I2U9YDrIcRDJrXhwE8BNMtnqE4owoLbFdrgzyf3Mei1fPj+PPv X/o9DHX/5nzHuXsral6sd+zl9sE4JMpN8b0PJO5ODrnHBe+T1LbOKG8ZEKs/fB1Itm 8z3vwcwQoEA3EkthtAh5KWfome5+iUm6oIgfO1RQV/5ik1ao9QPQpTJ/xZRju/YqRq wENWc4b2mbqQg== Received: from mchehab by mail.kernel.org with local (Exim 4.98) (envelope-from ) id 1sZX5H-00000001WCn-3My4; Thu, 01 Aug 2024 16:47:15 +0200 From: Mauro Carvalho Chehab To: Cc: Jonathan Cameron , Shiju Jose , Mauro Carvalho Chehab , "Michael S. Tsirkin" , Ani Sinha , Dongjiu Geng , Igor Mammedov , linux-kernel@vger.kernel.org, qemu-arm@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH v4 6/7] acpi/ghes: add support for generic error injection via QAPI Date: Thu, 1 Aug 2024 16:47:09 +0200 Message-ID: X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2604:1380:40e1:4800::1; envelope-from=mchehab+huawei@kernel.org; helo=sin.source.kernel.org X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.131, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Provide a generic interface for error injection via GHESv2. This patch is co-authored: - original ghes logic to inject a simple ARM record by Shiju Jose; - generic logic to handle block addresses by Jonathan Cameron; - generic GHESv2 error inject by Mauro Carvalho Chehab; Co-authored-by: Jonathan Cameron Co-authored-by: Shiju Jose Co-authored-by: Mauro Carvalho Chehab Cc: Jonathan Cameron Cc: Shiju Jose Signed-off-by: Mauro Carvalho Chehab --- hw/acpi/ghes.c | 159 ++++++++++++++++++++++++++++++++++++++--- hw/acpi/ghes_cper.c | 2 +- include/hw/acpi/ghes.h | 2 + 3 files changed, 151 insertions(+), 12 deletions(-) diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c index a745dcc7be5e..f5a05f4cb81d 100644 --- a/hw/acpi/ghes.c +++ b/hw/acpi/ghes.c @@ -395,23 +395,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) { start_addr += source_id * sizeof(uint64_t); @@ -448,9 +447,147 @@ 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_ack0 | + * | +---------------------+ --+-- + * | | read_ack1 | GHES_ADDRESS_SIZE + * | +---------------------+ --+-- + * | | ............. | + * | +---------------------+ + * | | read_ackN | + * | +---------------------+ --+-- + * | | 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_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_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; +} + NotifierList generic_error_notifiers = NOTIFIER_LIST_INITIALIZER(error_device_notifiers); +void ghes_record_cper_errors(AcpiGhesCper *cper, uint32_t notify) +{ + int read_ack = 0; + uint32_t i; + uint64_t read_ack_addr = 0; + uint64_t error_block_addr = 0; + uint32_t data_length; + GArray *block; + + if (!ghes_get_addr(notify, &error_block_addr, &read_ack_addr)) { + error_report("GHES: Invalid error block/ack address(es)"); + return; + } + + cpu_physical_memory_read(read_ack_addr, + &read_ack, sizeof(uint64_t)); + + /* zero means OSPM does not acknowledge the error */ + if (!read_ack) { + 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 = 1; + cpu_physical_memory_write(read_ack_addr, + &read_ack, sizeof(uint64_t)); + return; + } + + read_ack = cpu_to_le64(0); + cpu_physical_memory_write(read_ack_addr, + &read_ack, sizeof(uint64_t)); + + /* Build CPER record */ + + /* + * Invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data, + * Table 17-13 Generic Error Data Entry + */ + QemuUUID fru_id = {}; + + block = g_array_new(false, true /* clear */, 1); + data_length = ACPI_GHES_DATA_LENGTH + cper->data_len; + + /* + * It should not run out of the preallocated memory if + * adding a new generic error data entry + */ + assert((data_length + ACPI_GHES_GESB_SIZE) <= + ACPI_GHES_MAX_RAW_DATA_LENGTH); + + /* 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 this new generic error data entry header */ + acpi_ghes_generic_error_data(block, cper->uuid, + ACPI_CPER_SEV_RECOVERABLE, 0, 0, + cper->data_len, fru_id, 0); + + /* Add CPER data */ + for (i = 0; i < cper->data_len; i++) { + build_append_int_noprefix(block, cper->data[i], 1); + } + + /* Write the generic error data entry into guest memory */ + cpu_physical_memory_write(error_block_addr, block->data, block->len); + + g_array_free(block, true); + + notifier_list_notify(&generic_error_notifiers, NULL); +} + bool acpi_ghes_present(void) { AcpiGedState *acpi_ged_state; diff --git a/hw/acpi/ghes_cper.c b/hw/acpi/ghes_cper.c index 0d32874a84f1..504ba43ad0cc 100644 --- a/hw/acpi/ghes_cper.c +++ b/hw/acpi/ghes_cper.c @@ -47,7 +47,7 @@ void qmp_ghes_cper(CommonPlatformErrorRecord *qmp_cper, cper.data[i] = p->value; } - /* TODO: call a function at ghes */ + ghes_record_cper_errors(&cper, ACPI_GHES_NOTIFY_GPIO); g_free(cper.data); } diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h index 02ea3715f655..a426c47f2b96 100644 --- a/include/hw/acpi/ghes.h +++ b/include/hw/acpi/ghes.h @@ -84,6 +84,8 @@ typedef struct AcpiGhesCper { uint32_t data_len; } AcpiGhesCper; +void ghes_record_cper_errors(AcpiGhesCper *cper, uint32_t notify); + /** * acpi_ghes_present: Report whether ACPI GHES table is present * From patchwork Thu Aug 1 14:47:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mauro Carvalho Chehab X-Patchwork-Id: 13750601 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 3B1CEC3DA64 for ; Thu, 1 Aug 2024 14:48:06 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sZX5S-0001BQ-MH; Thu, 01 Aug 2024 10:47:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5O-0000wx-Uo for qemu-devel@nongnu.org; Thu, 01 Aug 2024 10:47:23 -0400 Received: from dfw.source.kernel.org ([2604:1380:4641:c500::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZX5L-0001qi-M7 for qemu-devel@nongnu.org; Thu, 01 Aug 2024 10:47:22 -0400 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id C0DA1628EA; Thu, 1 Aug 2024 14:47:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 940CFC32786; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1722523638; bh=J469TvAJbu9OT0Cil07DbO38OnPS8L+awPtnfxvDPSo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gN6Q4ysIMw+v+8CFFdoQg6KeqyzHSJ4rxFa71boQlJ2lqILHjkJyurjhvFp2aSVHd R8JGOvg9MVDKWmc+kh20tWdtBMMU8niLLCRnj0XG0hvL/s1iYwfd5T6H+5rIZoUTR4 00n0RoGS/c/7/ZJgJdBWi9K+D6CqCl9CzhfVoFu2YJ2LQNMwQTNHwK1+J7nP0Ku+27 dn+sI1/OSncOpOfF5+SiKA5r2IoQMCvhdlv1jTvxrJz5sPE/73rQ4VHZmbs8VO+7Hm ccUD4JHRAoG/XyCK/HnzPsfAzJw6p/UIXzXkCedpLCKbypiFFPFNgXQUQK7otaFomL tesLlDOfMzHaA== Received: from mchehab by mail.kernel.org with local (Exim 4.98) (envelope-from ) id 1sZX5H-00000001WCr-3Tj6; Thu, 01 Aug 2024 16:47:15 +0200 From: Mauro Carvalho Chehab To: Cc: Jonathan Cameron , Shiju Jose , Mauro Carvalho Chehab , Cleber Rosa , John Snow , linux-kernel@vger.kernel.org, qemu-devel@nongnu.org Subject: [PATCH v4 7/7] scripts/ghes_inject: add a script to generate GHES error inject Date: Thu, 1 Aug 2024 16:47:10 +0200 Message-ID: <0a9047370233f9e5b3363217d64ff2d93015466d.1722523312.git.mchehab+huawei@kernel.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2604:1380:4641:c500::1; envelope-from=mchehab+huawei@kernel.org; helo=dfw.source.kernel.org X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.131, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Using the QMP GHESv2 API requires preparing a raw data array containing a CPER record. Add a helper script with subcommands to prepare such data. Currently, only ARM Processor error CPER record is supported. Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 + scripts/ghes_inject.py | 673 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 674 insertions(+) create mode 100755 scripts/ghes_inject.py diff --git a/MAINTAINERS b/MAINTAINERS index 655edcb6688c..9e4874bb552d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2081,6 +2081,7 @@ S: Maintained F: hw/arm/ghes_cper.c F: hw/acpi/ghes_cper_stub.c F: qapi/ghes-cper.json +F: scripts/ghes_inject.py ppc4xx L: qemu-ppc@nongnu.org diff --git a/scripts/ghes_inject.py b/scripts/ghes_inject.py new file mode 100755 index 000000000000..99ee93bc2f34 --- /dev/null +++ b/scripts/ghes_inject.py @@ -0,0 +1,673 @@ +#!/usr/bin/env python3 +# +# pylint: disable=C0301, C0114, R0912, R0913, R0915, W0511 +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2024 Mauro Carvalho Chehab + +# TODO: current implementation has dummy defaults. +# +# For a better implementation, a QMP addition/call is needed to +# retrieve some data for ARM Processor Error injection: +# +# - machine emulation architecture, as ARM current default is +# for AArch64; +# - ARM registers: power_state, midr, mpidr. + +import argparse +import json +import socket +import sys + +EINJ_DESCRIPTION = """ +Handle ACPI GHESv2 error injection logic QEMU QMP interface.\n + +It allows using UEFI BIOS EINJ features to generate GHES records. + +It helps testing Linux CPER and GHES drivers and to test rasdaemon +error handling logic. + +Currently, it support ARM processor error injection for ARM processor +events, being compatible with UEFI 2.9A Errata. + +This small utility works together with those QEMU additions: +- https://gitlab.com/mchehab_kernel/qemu/-/tree/arm-error-inject-v2 +""" + + +# +# Socket QMP send command +# +def qmp_command(host, port, commands): + """Send commands to QEMU though QMP TCP socket""" + + # Needed to negotiate QMP and for QEMU to accept the command + commands.insert(0, '{ "execute": "qmp_capabilities" } ') + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((host, port)) + + data = s.recv(1024) + + print("\t", data.decode("utf-8"), end="") + + for command in commands: + print(command) + + s.sendall(command.encode("utf-8")) + data = s.recv(1024) + print("\t", data.decode("utf-8"), end="") + + s.shutdown(socket.SHUT_WR) + while 1: + data = s.recv(1024) + if data == b"": + break + print("\t", data.decode("utf-8")) + + s.close() + + +# +# Helper routines to handle multiple choice arguments +# +def get_choice(name, value, choices, suffixes=None): + """Produce a list from multiple choice argument""" + + new_values = [] + + if not value: + return new_values + + for val in value.split(","): + val = val.lower() + + if suffixes: + for suffix in suffixes: + val = val.removesuffix(suffix) + + if val not in choices.keys(): + sys.exit(f"Error on '{name}': choice {val} is invalid.") + + val = choices[val] + + new_values.append(val) + + return new_values + + +def get_mult_array(mult, name, values, allow_zero=False, max_val=None): + """Add numbered hashes from integer lists""" + + if not allow_zero: + if not values: + return + else: + if values is None: + return + + if not values: + i = 0 + if i not in mult: + mult[i] = {} + + mult[i][name] = [] + return + + i = 0 + for value in values: + for val in value.split(","): + try: + val = int(val, 0) + except ValueError: + sys.exit(f"Error on '{name}': {val} is not an integer") + + if val < 0: + sys.exit(f"Error on '{name}': {val} is not unsigned") + + if max_val and val > max_val: + sys.exit(f"Error on '{name}': {val} is too little") + + if i not in mult: + mult[i] = {} + + if name not in mult[i]: + mult[i][name] = [] + + mult[i][name].append(val) + + i += 1 + + +def get_mult_choices(mult, name, values, choices, + suffixes=None, allow_zero=False): + """Add numbered hashes from multiple choice arguments""" + + if not allow_zero: + if not values: + return + else: + if values is None: + return + + i = 0 + for val in values: + new_values = get_choice(name, val, choices, suffixes) + + if i not in mult: + mult[i] = {} + + mult[i][name] = new_values + i += 1 + + +def get_mult_int(mult, name, values, allow_zero=False): + """Add numbered hashes from integer arguments""" + if not allow_zero: + if not values: + return + else: + if values is None: + return + + i = 0 + for val in values: + try: + val = int(val, 0) + except ValueError: + sys.exit(f"Error on '{name}': {val} is not an integer") + + if val < 0: + sys.exit(f"Error on '{name}': {val} is not unsigned") + + if i not in mult: + mult[i] = {} + + mult[i][name] = val + i += 1 + + +# +# Data encode helper functions +# +def bit(b): + """Simple macro to define a bit on a bitmask""" + return 1 << b + + +def data_add(data, value, num_bytes): + """ + Adds bytes from value inside a bitarray. + If the value is a list, assume it to be a bitmap, where each + bit is on a different element inside a list. Such list is + converted to a single bitmap integer. + """ + + if isinstance(value, list): + bits = 0 + for b in value: + bits |= b + + value = bits + + data.extend(value.to_bytes(num_bytes, byteorder="little")) + + +def to_uuid(time_low, time_mid, time_high, nodes): + """Create an integer array with elements from an UUID""" + + values = bytearray() + + data_add(values, time_low, 4) + data_add(values, time_mid, 2) + data_add(values, time_high, 2) + + for i in nodes: + data_add(values, i, 1) + + return list(values) + + +# +# Arm processor EINJ logic +# +ACPI_GHES_ARM_CPER_LENGTH = 40 +ACPI_GHES_ARM_CPER_PEI_LENGTH = 32 + +# TODO: query it from emulation. Current default valid only for Aarch64 +CONTEXT_AARCH64_EL1 = 5 + +CPER_ARM_PROCESSOR_ERROR = to_uuid(0xE19E3D16, 0xBC11, 0x11E4, + [0x9C, 0xAA, 0xC2, 0x05, + 0x1D, 0x5D, 0x46, 0xB0]) + + +class ArmProcessorEinj: + """ + Implements ARM Processor Error injection via GHES + """ + + def __init__(self, args=None): + """ + Initialize the error injection class. There are two possible + ways to initialize it: + 1. passing a set of arguments; + 2. passing a dict with error inject command parameters. Each + column is handled in separate. + """ + + # Valid choice values + self.arm_valid_bits = { + "mpidr": bit(0), + "affinity": bit(1), + "running": bit(2), + "vendor": bit(3), + } + + self.pei_flags = { + "first": bit(0), + "last": bit(1), + "propagated": bit(2), + "overflow": bit(3), + } + + self.pei_error_types = { + "cache": bit(1), + "tlb": bit(2), + "bus": bit(3), + + "micro-arch": bit(4), + "vendor": bit(4), + } + + self.pei_valid_bits = { + "multiple-error": bit(0), + "flags": bit(1), + + "error": bit(2), + "error-info": bit(2), + + "virt": bit(3), + "virtual": bit(3), + + "phy": bit(4), + "physical": bit(4), + } + + self.arm = {} + + if not args: + self.args = args + return + + pei = {} + ctx = {} + vendor = {} + + # Handle global parameters + if args.arm: + arm_validation_init = False + self.arm["validation"] = get_choice(name="validation", + value=args.arm, + choices=self.arm_valid_bits, + suffixes=["-error", "-err"]) + else: + self.arm["validation"] = [] + arm_validation_init = True + + if args.affinity: + self.arm["affinity-level"] = args.affinity + if arm_validation_init: + self.arm["validation"].append(self.arm_valid_bits["affinity"]) + else: + self.arm["affinity-level"] = 0 + + if args.mpidr: + self.arm["mpidr-el1"] = args.mpidr + if arm_validation_init: + self.arm["validation"].append(self.arm_valid_bits["mpidr"]) + else: + # TODO: query it from emulation + self.arm["mpidr-el1"] = 0 + + if args.midr: + self.arm["midr-el1"] = args.midr + else: + # TODO: query it from emulation + self.arm["midr-el1"] = 0 + + if args.running is not None: + if args.running: + self.arm["running-state"] = bit(0) + else: + self.arm["running-state"] = 0 + if arm_validation_init: + self.arm["validation"].append(self.arm_valid_bits["running"]) + else: + # TODO: query it from emulation + self.arm["running-state"] = 0 + + if args.psci: + self.arm["psci-state"] = args.psci + if arm_validation_init: + self.arm["validation"].append(self.arm_valid_bits["running"]) + else: + # TODO: query it from emulation + self.arm["psci-state"] = 0 + + # Handle PEI + if not args.type: + args.type = ["cache-error"] + + get_mult_choices( + pei, + name="validation", + values=args.pei_valid, + choices=self.pei_valid_bits, + suffixes=["-valid", "-info", "--information", "--addr"], + ) + get_mult_choices( + pei, + name="type", + values=args.type, + choices=self.pei_error_types, + suffixes=["-error", "-err"], + ) + get_mult_choices( + pei, + name="flags", + values=args.flags, + choices=self.pei_flags, + suffixes=["-error", "-cap"], + ) + get_mult_int(pei, "error-info", args.error_info) + get_mult_int(pei, "multiple-error", args.multiple_error) + get_mult_int(pei, "phy-addr", args.physical_address) + get_mult_int(pei, "virt-addr", args.virtual_address) + + for i, p in pei.items(): # pylint: disable=W0612 + # UEFI 2.10 doesn't define how to encode error information + # when multiple types are raised. So, provide a default only + # if a single type is there + if "error-info" not in p: + if len(p["type"]) == 1: + if p["type"][0] == bit(1): + p["error-info"] = 0x0091000F + if p["type"][0] == bit(2): + p["error-info"] = 0x0054007F + if p["type"][0] == bit(3): + p["error-info"] = 0x80D6460FFF + if p["type"][0] == bit(4): + p["error-info"] = 0x78DA03FF + + if "validation" not in p: + p["validation"] = [] + if "multiple-error" in p: + p["validation"].append(self.pei_valid_bits["multiple-error"]) + + if "flags" in p: + p["validation"].append(self.pei_valid_bits["flags"]) + + if "error-info" in p: + p["validation"].append(self.pei_valid_bits["error-info"]) + + if "phy-addr" in p: + p["validation"].append(self.pei_valid_bits["phy-addr"]) + + if "virt-addr" in p: + p["validation"].append(self.pei_valid_bits["virt-addr"]) + + # Handle context + get_mult_int(ctx, "type", args.ctx_type, allow_zero=True) + get_mult_int(ctx, "minimal-size", args.ctx_size, allow_zero=True) + get_mult_array(ctx, "register", args.ctx_array, allow_zero=True) + + get_mult_array(vendor, "bytes", args.vendor, max_val=255) + + # Store PEI + self.arm["error"] = [] + for k in sorted(pei.keys()): + self.arm["error"].append(pei[k]) + + # Store Context + self.arm["context"] = [] + if ctx: + for k in sorted(ctx.keys()): + self.arm["context"].append(ctx[k]) + + # Vendor-specific bytes are not grouped + self.arm["vendor-specific"] = [] + if vendor: + for k in sorted(vendor.keys()): + self.arm["vendor-specific"] += vendor[k]["bytes"] + + def encode_pei(self): + """Encode bytes at the PEI table""" + + data = bytearray() + + for pei in self.arm["error"]: + # Version + data_add(data, 0, 1) + + data_add(data, ACPI_GHES_ARM_CPER_PEI_LENGTH, 1) + + data_add(data, pei["validation"], 2) + data_add(data, pei["type"], 1) + data_add(data, pei.get("multiple-error", 1), 2) + data_add(data, pei.get("flags", 0), 1) + data_add(data, pei.get("error_info", 0), 8) + data_add(data, pei.get("virt_addr", 0xDEADBEEF), 8) + data_add(data, pei.get("phy_addr", 0xABBA0BAD), 8) + + return data + + def encode_vendor(self): + """Encode bytes at the vendor data""" + + data = bytearray() + + for i in self.arm.get("vendor-specific", []): + data_add(data, i, 1) + + return data + + def encode_context(self): + """Encode bytes for the register context""" + + data = bytearray() + + if "context" not in self.arm: + return data + + for ctx in self.arm["context"]: + if "type" not in ctx: + ctx["type"] = CONTEXT_AARCH64_EL1 + + reg_size = len(ctx["register"]) + size = 0 + + if "minimal-size" in ctx: + size = ctx["minimal-size"] + + size = max(size, reg_size) + + size = (size + 1) % 0xFFFE + + # Version + data_add(data, 0, 2) + + data_add(data, ctx["type"], 2) + + data_add(data, 8 * size, 4) + + for r in ctx["register"]: + data_add(data, r, 8) + + for i in range(reg_size, size): # pylint: disable=W0612 + data_add(data, 0, 8) + + return data + + def encode(self): + """Encode bytes for the ARM processor Error record""" + + pei_data = self.encode_pei() + vendor_data = self.encode_vendor() + context_data = self.encode_context() + + data = bytearray() + + data_add(data, self.arm["validation"], 4) + + error_info_num = len(self.arm["error"]) + data_add(data, error_info_num, 2) + + context_info_num = len(self.arm["context"]) + data_add(data, context_info_num, 2) + + # Calculate the length of the CPER data + cper_length = ACPI_GHES_ARM_CPER_LENGTH + cper_length += len(pei_data) + cper_length += len(vendor_data) + cper_length += len(context_data) + data_add(data, cper_length, 4) + + data_add(data, self.arm["affinity-level"], 1) + + # Reserved + data_add(data, 0, 3) + + data_add(data, self.arm["mpidr-el1"], 8) + data_add(data, self.arm["midr-el1"], 8) + data_add(data, self.arm["running-state"], 4) + data_add(data, self.arm["psci-state"], 4) + + # Add PEI + data.extend(pei_data) + data.extend(context_data) + data.extend(vendor_data) + + return list(data) + + def run(self, host, port): + """Execute the QMP commands""" + + # Fill the commands to be sent + commands = [] + + cmd_arg = { + 'cper': { + 'notification-type': CPER_ARM_PROCESSOR_ERROR, + "raw-data": "" + } + } + + cmd_arg["cper"]["raw-data"] = self.encode() + + command = '{ "execute": "ghes-cper", ' + command += '"arguments": ' + json.dumps(cmd_arg) + " }" + + commands.append(command) + + qmp_command(host, port, commands) + + +# +# Argument parser for ARM Processor CPER +# + + +def arm_handle_args(subparsers): + """Add a subparser for ARM-specific arguments""" + + parser = subparsers.add_parser("arm", help="Generate an ARM processor CPER") + + # UEFI N.16 ARM Validation bits + g_arm = parser.add_argument_group("ARM processor") + g_arm.add_argument("--arm", "--arm-valid", + help="ARM validation bits: mpidr,affinity,running,vendor") + g_arm.add_argument("-a", "--affinity", "--level", "--affinity-level", + type=lambda x: int(x, 0), + help="Affinity level (when multiple levels apply)") + g_arm.add_argument("-l", "--mpidr", type=lambda x: int(x, 0), + help="Multiprocessor Affinity Register") + g_arm.add_argument("-i", "--midr", type=lambda x: int(x, 0), + help="Main ID Register") + g_arm.add_argument("-r", "--running", + action=argparse.BooleanOptionalAction, default=None, + help="Indicates if the processor is running or not") + g_arm.add_argument("--psci", "--psci-state", type=lambda x: int(x, 0), + help="Power State Coordination Interface - PSCI state") + + # TODO: Add vendor-specific support + + # UEFI N.17 bitmaps (type and flags) + g_pei = parser.add_argument_group("ARM Processor Error Info (PEI)") + g_pei.add_argument("-t", "--type", nargs="+", + help="one or more error types: cache,tlb,bus,vendor") + g_pei.add_argument("-f", "--flags", nargs="*", + help="zero or more error flags: first-error,last-error,propagated,overflow") + g_arm.add_argument("-V", "--pei-valid", "--error-valid", nargs="*", + help="zero or more PEI validation bits: multiple-error,flags,error-info,virt,phy") + + # UEFI N.17 Integer values + g_pei.add_argument("-m", "--multiple-error", nargs="+", + help="Number of errors: 0: Single error, 1: Multiple errors, 2-65535: Error count if known") + g_pei.add_argument("-e", "--error-info", nargs="+", + help="Error information (UEFI 2.10 tables N.18 to N.20)") + g_pei.add_argument("-p", "--physical-address", nargs="+", + help="Physical address") + g_pei.add_argument("-v", "--virtual-address", nargs="+", + help="Virtual address") + + # UEFI N.21 Context + g_pei.add_argument("--ctx-type", "--context-type", nargs="*", + help="Type of the context (0=ARM32 GPR, 5=ARM64 EL1, other values supported)") + g_pei.add_argument("--ctx-size", "--context-size", nargs="*", + help="Minimal size of the context") + g_pei.add_argument("--ctx-array", "--context-array", nargs="*", + help="Comma-separated arrays for each context") + + # Vendor-specific data + g_pei.add_argument("--vendor", "--vendor-specific", nargs="+", + help="Vendor-specific byte arrays of data") + + +# +# Main Program. Each error injection logic is handled by a separate subparser +# + + +def main(): + """Main program""" + + # Main parser - handle generic args like QEMU QMP TCP socket options + parser = argparse.ArgumentParser(prog="einj.py", + formatter_class=argparse.RawDescriptionHelpFormatter, + usage="%(prog)s [options]", + description=EINJ_DESCRIPTION, + epilog="If a field is not defined, a default value will be applied by QEMU.") + + g_options = parser.add_argument_group("QEMU QMP socket options") + g_options.add_argument("-H", "--host", default="localhost", type=str, + help="host name") + g_options.add_argument("-P", "--port", default=4445, type=int, + help="TCP port number") + + # Call subparsers + subparsers = parser.add_subparsers() + arm_handle_args(subparsers) + + args = parser.parse_args() + + # Handle subparser commands + if "arm" in args: + einj = ArmProcessorEinj(args) + einj.run(args.host, args.port) + else: + sys.exit("Error: type of error injection missing.") + + +if __name__ == "__main__": + main()