From nobody Sun Nov 24 13:28:34 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED8471EB4BF for ; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; cv=none; b=RCEYHi7bUAY+yU1+Z3Rq8ecRI2nVd3L5N0MKs7EAFCPvJQsFyP9eCsvcprqV0GiDKaWmN6avHxWtVtOZ5r3Nh8o7GF8FAL858FWAKLha7KWM2qloMh3MhJnKz2539R9ygKfu67aI8FTI7bC3G/7WcllY4PoTV76gCfoe8gWOvD0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; c=relaxed/simple; bh=wmX5BOavDV5A0y4JGTIfwXXXDCYeYux2q4KKf6xw9vs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=U/x7bzM3WEkIO2IbEl21BDCICv4OD723fi4N2U+866K/o6tZDXMzmK3Ap/tqiAfw2T3kyfCAFBsz0RmYVoKu0qqma5DwP2eYhtdpVTfkCWbZme1ZdkuLfonnvDXNllJ2MKQzfBlsWRV8zX42H35874cfUuoBeP1OLt3aQ0S4WT0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XEiVgpxR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XEiVgpxR" 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: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" 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 MemM= apEntry *gpio_memmap, aml_append(dev, aml_name_decl("_CRS", crs)); =20 Aml *aei =3D aml_resource_template(); - /* Pin 3 for power button */ - const uint32_t pin_list[1] =3D {3}; + + const uint32_t pin =3D 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)); =20 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 *opa= que) 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 =3D sysbus_create_simple("gpio-key", -1, - qdev_get_gpio_in(pl061_dev, 3)); + qdev_get_gpio_in(pl061_dev, + GPIO_PIN_POWER_BU= TTON)); =20 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); } =20 #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 =20 +/* GPIO pins */ +#define GPIO_PIN_POWER_BUTTON 3 + enum { VIRT_FLASH, VIRT_MEM, --=20 2.45.2 From nobody Sun Nov 24 13:28:34 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED8F2198A10 for ; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; cv=none; b=TYAnNeu2mAiYRlIWjN/I90GukxX6e0Eug4RRXd/B6vcSnC1LPXAVGN+rpiWxWRmh1PV/GWa+DpukSuJKugIpG4QMjPh6adP6K8VpDo93RhkvpMUctWco3Jzg5XU6ZWd7bGPHzf8MBwuqhufFLK8k2LjyzILYvtovtsi+w+v0FDs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; c=relaxed/simple; bh=lzZeLSx62/9+XmtaXqmWuty+3/8CulkJ9V68HTTwfN0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aTJlRIu+X4gQ1LzCqJHYMxwSkNx8twLY36GuRT9tr3t/ZnNvUirLDlIYSf75RZ/gG95XzlE5kgRhGQtDxPukycRO1Pu5npnEWbD8r9iZL8T0hU0e03SlbqOxnTqgp6+PFLrzxBsMXPanP2hZ7pkpGeEQ5eMYnMBP4ivkA5lmBek= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sPCMjIXc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sPCMjIXc" 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: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" 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-not= ification-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[] =3D { ACPI_GED_PWR_DOWN_EVT, ACPI_GED_NVDIMM_HOTPLUG_EVT, ACPI_GED_CPU_HOTPLUG_EVT, + ACPI_GED_ERROR_EVT }; =20 /* @@ -116,6 +117,11 @@ void build_ged_aml(Aml *table, const char *name, Hotpl= ugHandler *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); } =20 +void acpi_dsdt_add_error_device(Aml *scope) +{ + Aml *dev =3D 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, Acp= iEventStatusBits ev) sel =3D ACPI_GED_MEM_HOTPLUG_EVT; } else if (ev & ACPI_POWER_DOWN_STATUS) { sel =3D ACPI_GED_PWR_DOWN_EVT; + } else if (ev & ACPI_GENERIC_ERROR) { + sel =3D ACPI_GED_ERROR_EVT; } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) { sel =3D 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_de= v_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 =3D 16, ACPI_VMGENID_CHANGE_STATUS =3D 32, ACPI_POWER_DOWN_STATUS =3D 64, + ACPI_GENERIC_ERROR =3D 128, } AcpiEventStatusBits; =20 #define TYPE_ACPI_DEVICE_IF "acpi-device-interface" diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/gener= ic_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" =20 #define ACPI_POWER_BUTTON_DEVICE "PWRB" +#define ACPI_APEI_ERROR_DEVICE "GEDD" =20 #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 =20 typedef struct GEDState { MemoryRegion evt; @@ -120,5 +122,6 @@ struct AcpiGedState { void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_d= ev, 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); =20 #endif --=20 2.45.2 From nobody Sun Nov 24 13:28:34 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 22DFF1A6199 for ; Thu, 1 Aug 2024 14:47:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; cv=none; b=kteOJdVmXT9mv7xQWWercRJRQSjhw3p89XcOK3Se3NfCqDOUnMZ65+pMa2QZTOXjoEAl8FF6Dww/QtWiGQCfid5KrKSuQXFTsXjIi74cb67wXW50nTm0IFz3Y6xCXa9qO/rkKYcg7jQayx36f7VMt2Q1WNKvf/aESmWu8VJcVGk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; c=relaxed/simple; bh=rzo7GJ37SsXEzwNYx2lTpLxCPLuIqxbfFLqogTN1q0I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M1dm9Q9grgsAKnrVSjpQIpucCCv199Ov4buJQt2lq0FodR1CUA4aPOzcB6KW0szt602pp6BhcYSv4yVI8hfpeTg2ZOLN1gHPr8LvFxA8xt7ujbNpiYcfZAtOCvp4dPFNLq6yuBzUJJZuGx7SxHxDmnXZvB/ia8bZk0x7s2lMWXE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RSrEZGAX; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RSrEZGAX" 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: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" 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@i= ntel.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; } =20 +NotifierList generic_error_notifiers =3D + 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 MemMapE= ntry *memmap, static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, uint32_t gpio_irq) { + uint32_t pin; + Aml *dev =3D 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 MemMa= pEntry *gpio_memmap, =20 Aml *aei =3D aml_resource_template(); =20 - const uint32_t pin =3D GPIO_PIN_POWER_BUTTON; + pin =3D 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 =3D 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 MemMa= pEntry *gpio_memmap, aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), aml_int(0x80))); aml_append(dev, method); + + method =3D 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); } =20 @@ -841,10 +854,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, Vir= tMachineState *vms) HOTPLUG_HANDLER(vms->acpi_dev), irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEM= ORY, 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); =20 if (vms->acpi_dev) { uint32_t event =3D object_property_get_uint(OBJECT(vms->acpi_dev), @@ -858,6 +870,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, Virt= MachineState *vms) } =20 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(VirtMachineS= tate *vms) DeviceState *dev; MachineState *ms =3D MACHINE(vms); int irq =3D vms->irqmap[VIRT_ACPI_GED]; - uint32_t event =3D ACPI_GED_PWR_DOWN_EVT; + uint32_t event =3D ACPI_GED_PWR_DOWN_EVT | ACPI_GED_ERROR_EVT; =20 if (ms->ram_slots) { event |=3D ACPI_GED_MEM_HOTPLUG_EVT; @@ -1009,12 +1010,28 @@ static void virt_powerdown_req(Notifier *n, void *o= paque) } } =20 +static DeviceState *gpio_error_dev; +static void virt_generic_error_req(Notifier *n, void *opaque) +{ + VirtMachineState *s =3D container_of(n, VirtMachineState, generic_erro= r_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 =3D sysbus_create_simple("gpio-key", -1, qdev_get_gpio_in(pl061_dev, GPIO_PIN_POWER_BU= TTON)); + gpio_error_dev =3D sysbus_create_simple("gpio-key", -1, + qdev_get_gpio_in(pl061_dev, + GPIO_PIN_GENERI= C_ERROR)); =20 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) =20 if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)= ) { vms->acpi_dev =3D create_acpi_ged(vms); - } else { - create_gpio_devices(vms, VIRT_GPIO, sysmem); } + create_gpio_devices(vms, VIRT_GPIO, sysmem); =20 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 =3D virt_powerdown_req; qemu_register_powerdown_notifier(&vms->powerdown_notifier); =20 + vms->generic_error_notifier.notify =3D 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 =20 #include "hw/acpi/bios-linker-loader.h" +#include "qemu/notify.h" + +extern NotifierList generic_error_notifiers; =20 /* * 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 @@ =20 /* GPIO pins */ #define GPIO_PIN_POWER_BUTTON 3 +#define GPIO_PIN_GENERIC_ERROR 6 =20 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; --=20 2.45.2 From nobody Sun Nov 24 13:28:34 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED89C170858 for ; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; cv=none; b=dXlULiDuSMcSt2iLhgIoeT91T6QRgwrbzQvb76LygS8xWicLvfA+KqQgV/vJmGYx0Xr/o2i+FNJ8zIAKXWbd48lOhS1JxmeNf9/4zPYuVGJJON+IcCoMmkFANXCiAHC9tP0etYleEsDbZTKdojou1xQFf1xAreVbz4hL5C7jPwg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; c=relaxed/simple; bh=ZSlU9yW3n4NevgGhDHVq1qOszSSTbSe+VJ0pqN5i5yU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=B1ZUOvwNyka9OhLjIjeprn0x8XnUDVVU0XiIVLfn5iBs9eVzY+AYlfC/mNhwIPgsSopNU38snLr9VHTqTA4ZMgRYgDINO7Tpxfvg3Y5GqsNlnqY/yuOiQ8Czg9IBmF8aZTjjCa9sxPXncg+Zg1WGhY7OoB0UxrFtJCPolTC+6pk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b8yFjYE7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="b8yFjYE7" 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: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" 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) =20 -/* 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 =20 /* 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, BI= OSLinker *linker) static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *l= inker) { 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 sourc= e_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 *li= nker, /* 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); =20 acpi_table_end(linker, &table); } @@ -406,10 +413,7 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_= t physical_address) start_addr =3D le64_to_cpu(ags->ghes_addr_le); =20 if (physical_address) { - - if (source_id < ACPI_HEST_SRC_ID_RESERVED) { - start_addr +=3D source_id * sizeof(uint64_t); - } + start_addr +=3D source_id * sizeof(uint64_t); =20 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 =3D 12 }; =20 +/* Those are used as table indexes when building GHES tables */ enum { ACPI_HEST_SRC_ID_SEA =3D 0, - /* future ids go here */ + ACPI_HEST_SRC_ID_GPIO, ACPI_HEST_SRC_ID_RESERVED, }; =20 --=20 2.45.2 From nobody Sun Nov 24 13:28:34 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 09E061A6169 for ; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; cv=none; b=QQifbKCZFiZFHAVtUhOKfGgY26naBXC8mEWfEQNKFLD1tSQQ4bI3AV6cPOkecvRH9TUUNIiDvq6SLEiJI2pkrO4dHaK2e+4O1LA3nsx0wJM5P8BLe2vvIOpGwjVonXNR5f4f2peNuWYSl4LPyIgovpOeoeOovqKHEcuPZgOBmcI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; c=relaxed/simple; bh=inI4stFbv14+sS7oa5RIwxj/FX+TvJx1kVyZnVYHKuQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PpWN/TaxJjRXZQce8TH15YYy6cQIjen8QAqreG7287s9PbD0scDqsHJztzn+4/0ZtkKmwBnjSsBQZrQmIE1dOF/KIfdRCwZYh/CAxHyQ6XbMIH2lw/QPHwfwHZ7R8NylEiK6q5PCFgDsBDwoozwzurOgoZ6QLKCSSSVW72Scg7Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Si/dw9s7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Si/dw9s7" 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: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" 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 =20 +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 =20 +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 =3D 0, i; + uint8List *p; + AcpiGhesCper cper; + + for (p =3D qmp_cper->notification_type; p; p =3D p->next) { + uuid_len++; + if (uuid_len > 16) { + break; + } + cper.uuid[uuid_len - 1] =3D p->value; + } + + if (uuid_len !=3D 16) { + error_report("GHES CPER record has an invalid UUID size"); + return; + } + + cper.data_len =3D 0; + + for (p =3D qmp_cper->raw_data; p; p =3D p->next) { + cper.data_len++; + } + + cper.data =3D g_malloc(cper.data_len); + + p =3D qmp_cper->raw_data; + for (i =3D 0; i < cper.data_len; i++, p =3D p->next) { + cper.data[i] =3D 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-bui= ld-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); =20 +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=3Dpython + +## +# =3D 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 =3D [ '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' } --=20 2.45.2 From nobody Sun Nov 24 13:28:34 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 09E531A6177 for ; Thu, 1 Aug 2024 14:47:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; cv=none; b=A/lBzDgNV0+L28bVzPvGMYMGwmAlUgcu/mV7w0QX8RB6SBig9V72vDV7ygp+p02TfptM3VYrnWItQwkMsJm1MYRfyT27NNdXnvKLaJ+DmmXdp8/PpL4sdom2wYNBRScOnCMn2rVzClfNobwtzoXJDEVE6l+0Dhhk23gyhqjJ0v4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; c=relaxed/simple; bh=5vVNmeoIiLhqMUtCAtu3KNbQH6/d3NxIciD+hVX1/nw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Cn8E/46wkb8iGWXmUQC7Y7ZnmnGibDl75DRoTGZTcn0q1RyvWvHJLfrHYkWqy5wnR/mBe5pAy7C4Qs8DJrVBzBE+n01EEPjb1P3j+R3ZPjj6XKejBaibFCmpRbTkcTjoqV8wLatLt1vQGpBfSPDqtQSDXTDr71Yv7e7SaGhyopM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eRSBm+NA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eRSBm+NA" 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: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" 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, FWCfgSt= ate *s, ags->present =3D true; } =20 +static uint64_t ghes_get_state_start_address(void) +{ + AcpiGedState *acpi_ged_state =3D + ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, NULL)); + AcpiGhesState *ags =3D &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 = =3D 0; - uint64_t start_addr; + uint64_t start_addr =3D ghes_get_state_start_address(); bool ret =3D -1; - AcpiGedState *acpi_ged_state; - AcpiGhesState *ags; - assert(source_id < ACPI_HEST_SRC_ID_RESERVED); =20 - acpi_ged_state =3D ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED, - NULL)); - g_assert(acpi_ged_state); - ags =3D &acpi_ged_state->ghes_state; - - start_addr =3D le64_to_cpu(ags->ghes_addr_le); - if (physical_address) { start_addr +=3D source_id * sizeof(uint64_t); =20 @@ -448,9 +447,147 @@ int acpi_ghes_record_errors(uint8_t source_id, uint64= _t physical_address) return ret; } =20 +/* + * 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[] =3D { 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 >=3D ACPI_GHES_NOTIFY_RESERVED) { + return false; + } + + /* Find and check the source id for this new CPER */ + if (error_source_to_index[notify] =3D=3D 0xff) { + return false; + } + + base =3D ghes_get_state_start_address(); + + *read_ack_addr =3D 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 =3D 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 =3D NOTIFIER_LIST_INITIALIZER(error_device_notifiers); =20 +void ghes_record_cper_errors(AcpiGhesCper *cper, uint32_t notify) +{ + int read_ack =3D 0; + uint32_t i; + uint64_t read_ack_addr =3D 0; + uint64_t error_block_addr =3D 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 =3D 1; + cpu_physical_memory_write(read_ack_addr, + &read_ack, sizeof(uint64_t)); + return; + } + + read_ack =3D 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 =3D {}; + + block =3D g_array_new(false, true /* clear */, 1); + data_length =3D 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) <=3D + 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 =3D 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] =3D p->value; } =20 - /* TODO: call a function at ghes */ + ghes_record_cper_errors(&cper, ACPI_GHES_NOTIFY_GPIO); =20 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; =20 +void ghes_record_cper_errors(AcpiGhesCper *cper, uint32_t notify); + /** * acpi_ghes_present: Report whether ACPI GHES table is present * --=20 2.45.2 From nobody Sun Nov 24 13:28:34 2024 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 55D8B1A7F70 for ; Thu, 1 Aug 2024 14:47:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; cv=none; b=ndSaUlImbNyLqlzMe+bi1+N3ZgJYandlbXBQNZ9dmWnHqJ5KKHAY4H2wSV0d1Toggn6VgvnOVoUIC8PEL0KKqPW4pb/zoq6aK8vE3F9cDxSL8C3gYUpOM5Da16Qbw2u+vSrRbhHTv5sFNaxPGKoGZr9jJdOjGkEnHhdHfsSMtN8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722523638; c=relaxed/simple; bh=J469TvAJbu9OT0Cil07DbO38OnPS8L+awPtnfxvDPSo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p4l7oNMas2JtBFRwbrC9RFWE7AXmlP4eew0U2xB4f4ao0Qv/Cc64pHyHL0olkPaGj9xj+Oo0KEtOm6eoVZQK+ioJcv0genBZobamORabzEjTVL4VGGnd1VWanVfMnuxn8L/gAcrLkk95KnH9g8M22OuxczmjcEXcLRv2KRaX3S0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gN6Q4ysI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gN6Q4ysI" 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: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: Mauro Carvalho Chehab Content-Type: text/plain; charset="utf-8" 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 =20 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=3DC0301, 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 =3D """ +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 =3D socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((host, port)) + + data =3D s.recv(1024) + + print("\t", data.decode("utf-8"), end=3D"") + + for command in commands: + print(command) + + s.sendall(command.encode("utf-8")) + data =3D s.recv(1024) + print("\t", data.decode("utf-8"), end=3D"") + + s.shutdown(socket.SHUT_WR) + while 1: + data =3D s.recv(1024) + if data =3D=3D b"": + break + print("\t", data.decode("utf-8")) + + s.close() + + +# +# Helper routines to handle multiple choice arguments +# +def get_choice(name, value, choices, suffixes=3DNone): + """Produce a list from multiple choice argument""" + + new_values =3D [] + + if not value: + return new_values + + for val in value.split(","): + val =3D val.lower() + + if suffixes: + for suffix in suffixes: + val =3D val.removesuffix(suffix) + + if val not in choices.keys(): + sys.exit(f"Error on '{name}': choice {val} is invalid.") + + val =3D choices[val] + + new_values.append(val) + + return new_values + + +def get_mult_array(mult, name, values, allow_zero=3DFalse, max_val=3DNone): + """Add numbered hashes from integer lists""" + + if not allow_zero: + if not values: + return + else: + if values is None: + return + + if not values: + i =3D 0 + if i not in mult: + mult[i] =3D {} + + mult[i][name] =3D [] + return + + i =3D 0 + for value in values: + for val in value.split(","): + try: + val =3D 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] =3D {} + + if name not in mult[i]: + mult[i][name] =3D [] + + mult[i][name].append(val) + + i +=3D 1 + + +def get_mult_choices(mult, name, values, choices, + suffixes=3DNone, allow_zero=3DFalse): + """Add numbered hashes from multiple choice arguments""" + + if not allow_zero: + if not values: + return + else: + if values is None: + return + + i =3D 0 + for val in values: + new_values =3D get_choice(name, val, choices, suffixes) + + if i not in mult: + mult[i] =3D {} + + mult[i][name] =3D new_values + i +=3D 1 + + +def get_mult_int(mult, name, values, allow_zero=3DFalse): + """Add numbered hashes from integer arguments""" + if not allow_zero: + if not values: + return + else: + if values is None: + return + + i =3D 0 + for val in values: + try: + val =3D 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] =3D {} + + mult[i][name] =3D val + i +=3D 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 =3D 0 + for b in value: + bits |=3D b + + value =3D bits + + data.extend(value.to_bytes(num_bytes, byteorder=3D"little")) + + +def to_uuid(time_low, time_mid, time_high, nodes): + """Create an integer array with elements from an UUID""" + + values =3D 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 =3D 40 +ACPI_GHES_ARM_CPER_PEI_LENGTH =3D 32 + +# TODO: query it from emulation. Current default valid only for Aarch64 +CONTEXT_AARCH64_EL1 =3D 5 + +CPER_ARM_PROCESSOR_ERROR =3D 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=3DNone): + """ + 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 =3D { + "mpidr": bit(0), + "affinity": bit(1), + "running": bit(2), + "vendor": bit(3), + } + + self.pei_flags =3D { + "first": bit(0), + "last": bit(1), + "propagated": bit(2), + "overflow": bit(3), + } + + self.pei_error_types =3D { + "cache": bit(1), + "tlb": bit(2), + "bus": bit(3), + + "micro-arch": bit(4), + "vendor": bit(4), + } + + self.pei_valid_bits =3D { + "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 =3D {} + + if not args: + self.args =3D args + return + + pei =3D {} + ctx =3D {} + vendor =3D {} + + # Handle global parameters + if args.arm: + arm_validation_init =3D False + self.arm["validation"] =3D get_choice(name=3D"validation", + value=3Dargs.arm, + choices=3Dself.arm_valid_b= its, + suffixes=3D["-error", "-er= r"]) + else: + self.arm["validation"] =3D [] + arm_validation_init =3D True + + if args.affinity: + self.arm["affinity-level"] =3D args.affinity + if arm_validation_init: + self.arm["validation"].append(self.arm_valid_bits["affinit= y"]) + else: + self.arm["affinity-level"] =3D 0 + + if args.mpidr: + self.arm["mpidr-el1"] =3D 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"] =3D 0 + + if args.midr: + self.arm["midr-el1"] =3D args.midr + else: + # TODO: query it from emulation + self.arm["midr-el1"] =3D 0 + + if args.running is not None: + if args.running: + self.arm["running-state"] =3D bit(0) + else: + self.arm["running-state"] =3D 0 + if arm_validation_init: + self.arm["validation"].append(self.arm_valid_bits["running= "]) + else: + # TODO: query it from emulation + self.arm["running-state"] =3D 0 + + if args.psci: + self.arm["psci-state"] =3D 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"] =3D 0 + + # Handle PEI + if not args.type: + args.type =3D ["cache-error"] + + get_mult_choices( + pei, + name=3D"validation", + values=3Dargs.pei_valid, + choices=3Dself.pei_valid_bits, + suffixes=3D["-valid", "-info", "--information", "--addr"], + ) + get_mult_choices( + pei, + name=3D"type", + values=3Dargs.type, + choices=3Dself.pei_error_types, + suffixes=3D["-error", "-err"], + ) + get_mult_choices( + pei, + name=3D"flags", + values=3Dargs.flags, + choices=3Dself.pei_flags, + suffixes=3D["-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=3DW0612 + # 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"]) =3D=3D 1: + if p["type"][0] =3D=3D bit(1): + p["error-info"] =3D 0x0091000F + if p["type"][0] =3D=3D bit(2): + p["error-info"] =3D 0x0054007F + if p["type"][0] =3D=3D bit(3): + p["error-info"] =3D 0x80D6460FFF + if p["type"][0] =3D=3D bit(4): + p["error-info"] =3D 0x78DA03FF + + if "validation" not in p: + p["validation"] =3D [] + if "multiple-error" in p: + p["validation"].append(self.pei_valid_bits["multiple-e= rror"]) + + 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=3DTrue) + get_mult_int(ctx, "minimal-size", args.ctx_size, allow_zero=3DTrue) + get_mult_array(ctx, "register", args.ctx_array, allow_zero=3DTrue) + + get_mult_array(vendor, "bytes", args.vendor, max_val=3D255) + + # Store PEI + self.arm["error"] =3D [] + for k in sorted(pei.keys()): + self.arm["error"].append(pei[k]) + + # Store Context + self.arm["context"] =3D [] + if ctx: + for k in sorted(ctx.keys()): + self.arm["context"].append(ctx[k]) + + # Vendor-specific bytes are not grouped + self.arm["vendor-specific"] =3D [] + if vendor: + for k in sorted(vendor.keys()): + self.arm["vendor-specific"] +=3D vendor[k]["bytes"] + + def encode_pei(self): + """Encode bytes at the PEI table""" + + data =3D 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 =3D 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 =3D bytearray() + + if "context" not in self.arm: + return data + + for ctx in self.arm["context"]: + if "type" not in ctx: + ctx["type"] =3D CONTEXT_AARCH64_EL1 + + reg_size =3D len(ctx["register"]) + size =3D 0 + + if "minimal-size" in ctx: + size =3D ctx["minimal-size"] + + size =3D max(size, reg_size) + + size =3D (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=3DW0612 + data_add(data, 0, 8) + + return data + + def encode(self): + """Encode bytes for the ARM processor Error record""" + + pei_data =3D self.encode_pei() + vendor_data =3D self.encode_vendor() + context_data =3D self.encode_context() + + data =3D bytearray() + + data_add(data, self.arm["validation"], 4) + + error_info_num =3D len(self.arm["error"]) + data_add(data, error_info_num, 2) + + context_info_num =3D len(self.arm["context"]) + data_add(data, context_info_num, 2) + + # Calculate the length of the CPER data + cper_length =3D ACPI_GHES_ARM_CPER_LENGTH + cper_length +=3D len(pei_data) + cper_length +=3D len(vendor_data) + cper_length +=3D 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 =3D [] + + cmd_arg =3D { + 'cper': { + 'notification-type': CPER_ARM_PROCESSOR_ERROR, + "raw-data": "" + } + } + + cmd_arg["cper"]["raw-data"] =3D self.encode() + + command =3D '{ "execute": "ghes-cper", ' + command +=3D '"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 =3D subparsers.add_parser("arm", help=3D"Generate an ARM proces= sor CPER") + + # UEFI N.16 ARM Validation bits + g_arm =3D parser.add_argument_group("ARM processor") + g_arm.add_argument("--arm", "--arm-valid", + help=3D"ARM validation bits: mpidr,affinity,running= ,vendor") + g_arm.add_argument("-a", "--affinity", "--level", "--affinity-level", + type=3Dlambda x: int(x, 0), + help=3D"Affinity level (when multiple levels apply)= ") + g_arm.add_argument("-l", "--mpidr", type=3Dlambda x: int(x, 0), + help=3D"Multiprocessor Affinity Register") + g_arm.add_argument("-i", "--midr", type=3Dlambda x: int(x, 0), + help=3D"Main ID Register") + g_arm.add_argument("-r", "--running", + action=3Dargparse.BooleanOptionalAction, default=3D= None, + help=3D"Indicates if the processor is running or no= t") + g_arm.add_argument("--psci", "--psci-state", type=3Dlambda x: int(x, 0= ), + help=3D"Power State Coordination Interface - PSCI s= tate") + + # TODO: Add vendor-specific support + + # UEFI N.17 bitmaps (type and flags) + g_pei =3D parser.add_argument_group("ARM Processor Error Info (PEI)") + g_pei.add_argument("-t", "--type", nargs=3D"+", + help=3D"one or more error types: cache,tlb,bus,vend= or") + g_pei.add_argument("-f", "--flags", nargs=3D"*", + help=3D"zero or more error flags: first-error,last-= error,propagated,overflow") + g_arm.add_argument("-V", "--pei-valid", "--error-valid", nargs=3D"*", + help=3D"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=3D"+", + help=3D"Number of errors: 0: Single error, 1: Multi= ple errors, 2-65535: Error count if known") + g_pei.add_argument("-e", "--error-info", nargs=3D"+", + help=3D"Error information (UEFI 2.10 tables N.18 to= N.20)") + g_pei.add_argument("-p", "--physical-address", nargs=3D"+", + help=3D"Physical address") + g_pei.add_argument("-v", "--virtual-address", nargs=3D"+", + help=3D"Virtual address") + + # UEFI N.21 Context + g_pei.add_argument("--ctx-type", "--context-type", nargs=3D"*", + help=3D"Type of the context (0=3DARM32 GPR, 5=3DARM= 64 EL1, other values supported)") + g_pei.add_argument("--ctx-size", "--context-size", nargs=3D"*", + help=3D"Minimal size of the context") + g_pei.add_argument("--ctx-array", "--context-array", nargs=3D"*", + help=3D"Comma-separated arrays for each context") + + # Vendor-specific data + g_pei.add_argument("--vendor", "--vendor-specific", nargs=3D"+", + help=3D"Vendor-specific byte arrays of data") + + +# +# Main Program. Each error injection logic is handled by a separate subpar= ser +# + + +def main(): + """Main program""" + + # Main parser - handle generic args like QEMU QMP TCP socket options + parser =3D argparse.ArgumentParser(prog=3D"einj.py", + formatter_class=3Dargparse.RawDescrip= tionHelpFormatter, + usage=3D"%(prog)s [options]", + description=3DEINJ_DESCRIPTION, + epilog=3D"If a field is not defined, = a default value will be applied by QEMU.") + + g_options =3D parser.add_argument_group("QEMU QMP socket options") + g_options.add_argument("-H", "--host", default=3D"localhost", type=3Ds= tr, + help=3D"host name") + g_options.add_argument("-P", "--port", default=3D4445, type=3Dint, + help=3D"TCP port number") + + # Call subparsers + subparsers =3D parser.add_subparsers() + arm_handle_args(subparsers) + + args =3D parser.parse_args() + + # Handle subparser commands + if "arm" in args: + einj =3D ArmProcessorEinj(args) + einj.run(args.host, args.port) + else: + sys.exit("Error: type of error injection missing.") + + +if __name__ =3D=3D "__main__": + main() --=20 2.45.2