From patchwork Mon Mar 22 22:37:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Erik Kaneda X-Patchwork-Id: 406207 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A272C433E0 for ; Mon, 22 Mar 2021 23:10:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F1585619A3 for ; Mon, 22 Mar 2021 23:10:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230272AbhCVXKL (ORCPT ); Mon, 22 Mar 2021 19:10:11 -0400 Received: from mga06.intel.com ([134.134.136.31]:20269 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230189AbhCVXJj (ORCPT ); Mon, 22 Mar 2021 19:09:39 -0400 IronPort-SDR: H5grCUC5XridzWYU9YqUvRLKASVC0FJCpJhrKFLubj2ssl1ozfz11E44dC1QPq+N7zHSaW3kgs OIbWO/XmVO6g== X-IronPort-AV: E=McAfee;i="6000,8403,9931"; a="251718882" X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="251718882" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Mar 2021 16:09:37 -0700 IronPort-SDR: wYVmKeg8Xd0M1rXiJB3+IgeTYRcJVGdqZbT+Pau1KEvpPS0csk2tft1dHGaRLHihBYfC6xG3g/ lzPWfyy9Q+5A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="607510496" Received: from sibelius.jf.intel.com ([10.54.75.166]) by fmsmga005.fm.intel.com with ESMTP; 22 Mar 2021 16:09:37 -0700 From: Erik Kaneda To: "Rafael J . Wysocki" , ACPI Devel Maling List Cc: Erik Kaneda Subject: [PATCH v3 1/4] ACPICA: iASL: add disassembler support for PRMT Date: Mon, 22 Mar 2021 15:37:04 -0700 Message-Id: <20210322223707.1838823-2-erik.kaneda@intel.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210322223707.1838823-1-erik.kaneda@intel.com> References: <20210322223707.1838823-1-erik.kaneda@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Signed-off-by: Erik Kaneda --- include/acpi/actbl2.h | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index d6478c430c99..3b6434fc3f3c 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -38,6 +38,7 @@ #define ACPI_SIG_PDTT "PDTT" /* Platform Debug Trigger Table */ #define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */ #define ACPI_SIG_PPTT "PPTT" /* Processor Properties Topology Table */ +#define ACPI_SIG_PRMT "PRMT" /* Platform Runtime Mechanism Table */ #define ACPI_SIG_RASF "RASF" /* RAS Feature table */ #define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ #define ACPI_SIG_SDEI "SDEI" /* Software Delegated Exception Interface Table */ @@ -1528,6 +1529,45 @@ struct acpi_pptt_id { u16 spin_rev; }; +/******************************************************************************* + * + * PRMT - Platform Runtime Mechanism Table + * Version 1 + * + ******************************************************************************/ + +struct acpi_table_prmt { + struct acpi_table_header header; + u8 platform_guid[16]; + u32 module_offset; + u32 module_count; +}; + +struct acpi_prmt_module_header { + u16 revision; + u16 length; +}; + +struct acpi_prmt_module_info { + u16 revision; + u16 length; + u8 guid[16]; + u16 major_rev; + u16 minor_rev; + u16 handler_count; + u32 handler_offset; + u64 mmio_list_pointer; +}; + +struct acpi_prmt_handler_info { + u16 revision; + u16 length; + u8 guid[16]; + u64 address; + u64 static_data_buffer_address; + u64 acpi_param_buffer_address; +}; + /******************************************************************************* * * RASF - RAS Feature Table (ACPI 5.0) From patchwork Mon Mar 22 22:37:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Erik Kaneda X-Patchwork-Id: 406206 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8502DC433E1 for ; Mon, 22 Mar 2021 23:10:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 56BF1619A4 for ; Mon, 22 Mar 2021 23:10:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230189AbhCVXKM (ORCPT ); Mon, 22 Mar 2021 19:10:12 -0400 Received: from mga06.intel.com ([134.134.136.31]:20267 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230167AbhCVXJj (ORCPT ); Mon, 22 Mar 2021 19:09:39 -0400 IronPort-SDR: mCsnSVcirBx9ct9KCaUco82pCgY1rspmWjBXdGbWVXMn9sIN9oUEyCCU8akEEE6g+blaiKdY7e Tt5O/tdZmQEw== X-IronPort-AV: E=McAfee;i="6000,8403,9931"; a="251718883" X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="251718883" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Mar 2021 16:09:37 -0700 IronPort-SDR: hC0Sogm/hJ4oAUyOQRuXJ3TUSRX1YIm9Uzw5IGRT2kVsftQzFYk8UphCU74lF3BpcUyv4GL+GU axiF7XswcS8w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="607510499" Received: from sibelius.jf.intel.com ([10.54.75.166]) by fmsmga005.fm.intel.com with ESMTP; 22 Mar 2021 16:09:37 -0700 From: Erik Kaneda To: "Rafael J . Wysocki" , ACPI Devel Maling List Cc: Erik Kaneda Subject: [PATCH v3 2/4] ACPICA: Add support for PlatformRtMechanism OperationRegion handler Date: Mon, 22 Mar 2021 15:37:05 -0700 Message-Id: <20210322223707.1838823-3-erik.kaneda@intel.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210322223707.1838823-1-erik.kaneda@intel.com> References: <20210322223707.1838823-1-erik.kaneda@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Writing a buffer to a PlatformRtMechanism fieldunit invokes a bidirectional transaction. The input buffer contains 26 bytes containing 9 bytes of status, a command byte and a 16-byte UUID. This change will will simply pass this incoming buffer to a handler registered by the OS. Signed-off-by: Erik Kaneda --- drivers/acpi/acpica/acutils.h | 2 ++ drivers/acpi/acpica/exfield.c | 8 +++++-- drivers/acpi/acpica/exserial.c | 12 ++++++++++ drivers/acpi/acpica/utuuid.c | 41 ++++++++++++++++++++++++++++++++++ include/acpi/acconfig.h | 2 ++ 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index be6de7149e67..dd72d589babe 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -736,6 +736,8 @@ const char *acpi_ah_match_uuid(u8 *data); */ #if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_HELP_APP) void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer); + +acpi_status acpi_ut_convert_uuid_to_string(char *uuid_buffer, char *out_string); #endif #endif /* _ACUTILS_H */ diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 32f03ee81785..06f3c9df1e22 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -139,7 +139,9 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_IPMI)) { + ACPI_ADR_SPACE_IPMI + || obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_PLATFORM_RT)) { /* SMBus, GSBus, IPMI serial */ @@ -301,7 +303,9 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_IPMI)) { + ACPI_ADR_SPACE_IPMI + || obj_desc->field.region_obj->region.space_id == + ACPI_ADR_SPACE_PLATFORM_RT)) { /* SMBus, GSBus, IPMI serial */ diff --git a/drivers/acpi/acpica/exserial.c b/drivers/acpi/acpica/exserial.c index 8e8d95f7947b..10d68a5f76a3 100644 --- a/drivers/acpi/acpica/exserial.c +++ b/drivers/acpi/acpica/exserial.c @@ -195,6 +195,12 @@ acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc, function = ACPI_READ | (accessor_type << 16); break; + case ACPI_ADR_SPACE_PLATFORM_RT: + + buffer_length = ACPI_PRM_INPUT_BUFFER_SIZE; + function = ACPI_READ; + break; + default: return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } @@ -311,6 +317,12 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc, function = ACPI_WRITE | (accessor_type << 16); break; + case ACPI_ADR_SPACE_PLATFORM_RT: + + buffer_length = ACPI_PRM_INPUT_BUFFER_SIZE; + function = ACPI_WRITE; + break; + default: return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } diff --git a/drivers/acpi/acpica/utuuid.c b/drivers/acpi/acpica/utuuid.c index 090e44b6b6c7..dca9061518ab 100644 --- a/drivers/acpi/acpica/utuuid.c +++ b/drivers/acpi/acpica/utuuid.c @@ -61,4 +61,45 @@ void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer) 1]); } } + +/******************************************************************************* + * + * FUNCTION: acpi_ut_convert_uuid_to_string + * + * PARAMETERS: uuid_buffer - 16-byte UUID buffer + * out_string - 36-byte formatted UUID string + * + * RETURN: Status + * + * DESCRIPTION: Convert 16-byte UUID buffer to 36-byte formatted UUID string + * out_string must be 37 bytes to include null terminator. + * + ******************************************************************************/ + +acpi_status acpi_ut_convert_uuid_to_string(char *uuid_buffer, char *out_string) +{ + u32 i; + + if (!uuid_buffer || !out_string) { + return (AE_BAD_PARAMETER); + } + + for (i = 0; i < UUID_BUFFER_LENGTH; i++) { + out_string[acpi_gbl_map_to_uuid_offset[i]] = + acpi_ut_hex_to_ascii_char(uuid_buffer[i], 4); + + out_string[acpi_gbl_map_to_uuid_offset[i] + 1] = + acpi_ut_hex_to_ascii_char(uuid_buffer[i], 0); + } + + /* Insert required hyphens (dashes) */ + + out_string[UUID_HYPHEN1_OFFSET] = + out_string[UUID_HYPHEN2_OFFSET] = + out_string[UUID_HYPHEN3_OFFSET] = + out_string[UUID_HYPHEN4_OFFSET] = '-'; + + out_string[UUID_STRING_LENGTH] = 0; /* Null terminate */ + return (AE_OK); +} #endif diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index e92f84fa8c68..0362cbb72359 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -188,6 +188,8 @@ #define ACPI_MAX_GSBUS_DATA_SIZE 255 #define ACPI_MAX_GSBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_MAX_GSBUS_DATA_SIZE +#define ACPI_PRM_INPUT_BUFFER_SIZE 26 + /* _sx_d and _sx_w control methods */ #define ACPI_NUM_sx_d_METHODS 4 From patchwork Mon Mar 22 22:37:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Erik Kaneda X-Patchwork-Id: 406205 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9EA52C433E3 for ; Mon, 22 Mar 2021 23:10:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3C377619AE for ; Mon, 22 Mar 2021 23:10:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230274AbhCVXKL (ORCPT ); Mon, 22 Mar 2021 19:10:11 -0400 Received: from mga06.intel.com ([134.134.136.31]:20267 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230272AbhCVXJj (ORCPT ); Mon, 22 Mar 2021 19:09:39 -0400 IronPort-SDR: Lrcq6HrKQ6cxD3r7YbBgPenXoIXi5uTxpYsjZTWmt80Nu69Nh13TC7xYbeLxE8Y0RBjPkhLb50 NEX7YtRBIJYQ== X-IronPort-AV: E=McAfee;i="6000,8403,9931"; a="251718884" X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="251718884" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Mar 2021 16:09:38 -0700 IronPort-SDR: V6pwEcKSYLEIhp8Y9+mh+J2KruorKa8Z0zRe4mR/XRAUE8GuCyamJFV7HMLHfxaln1x6obA4Nt /z2p/F2j8Zag== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="607510505" Received: from sibelius.jf.intel.com ([10.54.75.166]) by fmsmga005.fm.intel.com with ESMTP; 22 Mar 2021 16:09:37 -0700 From: Erik Kaneda To: "Rafael J . Wysocki" , ACPI Devel Maling List Cc: Erik Kaneda , Dan Williams , Ashok Raj , Rafael Wysocki Subject: [PATCH v3 3/4] PRM: implement OperationRegion handler for the PlatformRtMechanism subtype Date: Mon, 22 Mar 2021 15:37:06 -0700 Message-Id: <20210322223707.1838823-4-erik.kaneda@intel.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210322223707.1838823-1-erik.kaneda@intel.com> References: <20210322223707.1838823-1-erik.kaneda@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Platform Runtime Mechanism (PRM) is a firmware interface that exposes a set of binary executables that can either be called from the AML interpreter or device drivers by bypassing the AML interpreter. This change implements the AML interpreter path. According to the specification [1], PRM services are listed in an ACPI table called the PRMT. This patch parses module and handler information listed in the PRMT and registers the PlatformRtMechanism OpRegion handler before ACPI tables are loaded. Each service is defined by a 16-byte GUID and called from writing a 26-byte ASL buffer containing the identifier to a FieldUnit object defined inside a PlatformRtMechanism OperationRegion. OperationRegion (PRMR, PlatformRtMechanism, 0, 26) Field (PRMR, BufferAcc, NoLock, Preserve) { PRMF, 208 // Write to this field to invoke the OperationRegion Handler } The 26-byte ASL buffer is defined as the following: Byte Offset Byte Length Description ============================================================= 0 1 PRM OperationRegion handler status 1 8 PRM service status 9 1 PRM command 10 16 PRM handler GUID The ASL caller fills out a 26-byte buffer containing the PRM command and the PRM handler GUID like so: /* Local0 is the PRM data buffer */ Local0 = buffer (26){} /* Create byte fields over the buffer */ CreateByteField (Local0, 0x9, CMD) CreateField (Local0, 0x50, 0x80, GUID) /* Fill in the command and data fields of the data buffer */ CMD = 0 // run command GUID = ToUUID("xxxx-xx-xxx-xxxx") /* * Invoke PRM service with an ID that matches GUID and save the * result. */ Local0 = (\_SB.PRMT.PRMF = Local0) Byte offset 0 - 8 are written by the handler as a status passed back to AML and used by ASL like so: /* Create byte fields over the buffer */ CreateByteField (Local0, 0x0, PSTA) CreateQWordField (Local0, 0x1, USTA) In this ASL code, PSTA contains a status from the OperationRegion and USTA contains a status from the PRM service. The 26-byte buffer is recieved by acpi_platformrt_space_handler. This handler will look at the command value and the handler guid and take the approperiate actions. Command value Action ===================================================================== 0 Run the PRM service indicated by the PRM handler GUID (bytes 10-26) 1 Prevent PRM runtime updates from happening to the service's parent module 2 Allow PRM updates from happening to the service's parent module Note: PRM service updates will be implemented in future patches. This patch enables command value 0. [1] https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mechanism%20-%20with%20legal%20notice.pdf Cc: Dan Williams Cc: Ashok Raj Cc: Rafael Wysocki Signed-off-by: Erik Kaneda --- drivers/acpi/Kconfig | 5 + drivers/acpi/Makefile | 1 + drivers/acpi/bus.c | 2 + drivers/acpi/prmt.c | 302 ++++++++++++++++++++++++++++++++++++++++++ drivers/acpi/tables.c | 9 ++ include/linux/acpi.h | 1 + include/linux/prmt.h | 7 + 7 files changed, 327 insertions(+) create mode 100644 drivers/acpi/prmt.c create mode 100644 include/linux/prmt.h diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index eedec61e3476..3972de7b7565 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -543,3 +543,8 @@ config X86_PM_TIMER You should nearly always say Y here because many modern systems require this timer. + +config ACPI_PRMT + bool "Platform Runtime Mechanism Support" + depends on EFI && X86_64 + default y diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 700b41adf2db..efb0d1f64019 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -61,6 +61,7 @@ acpi-$(CONFIG_ACPI_FPDT) += acpi_fpdt.o acpi-$(CONFIG_ACPI_LPIT) += acpi_lpit.o acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o +acpi-$(CONFIG_ACPI_PRMT) += prmt.o # Address translation acpi-$(CONFIG_ACPI_ADXL) += acpi_adxl.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index be7da23fad76..3484497923d5 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" @@ -1330,6 +1331,7 @@ static int __init acpi_init(void) acpi_kobj = NULL; } + init_prmt(); result = acpi_bus_init(); if (result) { disable_acpi(); diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c new file mode 100644 index 000000000000..2bc28bdf0998 --- /dev/null +++ b/drivers/acpi/prmt.c @@ -0,0 +1,302 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Author: Erik Kaneda + * Copyright 2020 Intel Corporation + * + * prmt.c + * + * Each PRM service is an executable that is run in a restricted environment + * that is invoked by writing to the PlatformRtMechanism OperationRegion from + * AML bytecode. + * + * init_prmt initializes the Platform Runtime Mechanism (PRM) services by + * processing data in the PRMT as well as registering an ACPI OperationRegion + * handler for the PlatformRtMechanism subtype. + * + */ +#include +#include +#include +#include +#include + +#pragma pack(1) +struct prm_mmio_addr_range { + u64 phys_addr; + u64 virt_addr; + u32 length; +}; + +struct prm_mmio_info { + u64 mmio_count; + struct prm_mmio_addr_range addr_ranges[]; +}; + +struct prm_buffer { + u8 prm_status; + u64 efi_status; + u8 prm_cmd; + guid_t handler_guid; +}; + +struct prm_context_buffer { + char signature[ACPI_NAMESEG_SIZE]; + u16 revision; + u16 reserved; + guid_t identifier; + u64 static_data_buffer; + struct prm_mmio_info *mmio_ranges; +}; +#pragma pack() + + +LIST_HEAD(prm_module_list); + +struct prm_handler_info { + guid_t guid; + u64 handler_addr; + u64 static_data_buffer_addr; + u64 acpi_param_buffer_addr; + + struct list_head handler_list; +}; + +struct prm_module_info { + guid_t guid; + u16 major_rev; + u16 minor_rev; + u16 handler_count; + struct prm_mmio_info *mmio_info; + bool updatable; + + struct list_head module_list; + struct prm_handler_info handlers[]; +}; + + +static u64 efi_pa_va_lookup(u64 pa) +{ + efi_memory_desc_t *md; + u64 pa_offset = pa & ~PAGE_MASK; + u64 page = pa & PAGE_MASK; + + for_each_efi_memory_desc(md) { + if (md->phys_addr < pa && pa < md->phys_addr + PAGE_SIZE * md->num_pages) + return pa_offset + md->virt_addr + page - md->phys_addr; + } + + return 0; +} + + +#define get_first_handler(a) ((struct acpi_prmt_handler_info *) ((char *) (a) + a->handler_offset)) +#define get_next_handler(a) ((struct acpi_prmt_handler_info *) (sizeof(struct acpi_prmt_handler_info) + (char *) a)) + +static int __init +acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end) +{ + struct acpi_prmt_module_info *module_info; + struct acpi_prmt_handler_info *handler_info; + struct prm_handler_info *th; + struct prm_module_info *tm; + u64 mmio_count = 0; + u64 cur_handler = 0; + u32 module_info_size = 0; + u64 mmio_range_size = 0; + void *temp_mmio; + + module_info = (struct acpi_prmt_module_info *) header; + module_info_size = struct_size(tm, handlers, module_info->handler_count); + tm = kmalloc(module_info_size, GFP_KERNEL); + + guid_copy(&tm->guid, (guid_t *) module_info->guid); + tm->major_rev = module_info->major_rev; + tm->minor_rev = module_info->minor_rev; + tm->handler_count = module_info->handler_count; + tm->updatable = true; + + if (module_info->mmio_list_pointer) { + /* + * Each module is associated with a list of addr + * ranges that it can use during the service + */ + mmio_count = *(u64 *) memremap(module_info->mmio_list_pointer, 8, MEMREMAP_WB); + mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count); + tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL); + temp_mmio = memremap(module_info->mmio_list_pointer, mmio_range_size, MEMREMAP_WB); + memmove(tm->mmio_info, temp_mmio, mmio_range_size); + } else { + mmio_range_size = struct_size(tm->mmio_info, addr_ranges, mmio_count); + tm->mmio_info = kmalloc(mmio_range_size, GFP_KERNEL); + tm->mmio_info->mmio_count = 0; + } + + INIT_LIST_HEAD(&tm->module_list); + list_add(&tm->module_list, &prm_module_list); + + handler_info = get_first_handler(module_info); + do { + th = &tm->handlers[cur_handler]; + + guid_copy(&th->guid, (guid_t *)handler_info->guid); + th->handler_addr = efi_pa_va_lookup(handler_info->address); + th->static_data_buffer_addr = efi_pa_va_lookup(handler_info->static_data_buffer_address); + th->acpi_param_buffer_addr = efi_pa_va_lookup(handler_info->acpi_param_buffer_address); + } while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info))); + + return 0; +} + +#define GET_MODULE 0 +#define GET_HANDLER 1 + +static void *find_guid_info(const guid_t *guid, u8 mode) +{ + struct prm_handler_info *cur_handler; + struct prm_module_info *cur_module; + int i = 0; + + list_for_each_entry(cur_module, &prm_module_list, module_list) { + for (i = 0; i < cur_module->handler_count; ++i) { + cur_handler = &cur_module->handlers[i]; + if (guid_equal(guid, &cur_handler->guid)) { + if (mode == GET_MODULE) + return (void *)cur_module; + else + return (void *)cur_handler; + } + } + } + + return NULL; +} + + +static struct prm_module_info *find_prm_module(const guid_t *guid) +{ + return (struct prm_module_info *)find_guid_info(guid, GET_MODULE); +} + +static struct prm_handler_info *find_prm_handler(const guid_t *guid) +{ + return (struct prm_handler_info *) find_guid_info(guid, GET_HANDLER); +} + +/* In-coming PRM commands */ + +#define PRM_CMD_RUN_SERVICE 0 +#define PRM_CMD_START_TRANSACTION 1 +#define PRM_CMD_END_TRANSACTION 2 + +/* statuses that can be passed back to ASL */ + +#define PRM_HANDLER_SUCCESS 0 +#define PRM_HANDLER_ERROR 1 +#define INVALID_PRM_COMMAND 2 +#define PRM_HANDLER_GUID_NOT_FOUND 3 +#define UPDATE_LOCK_ALREADY_HELD 4 +#define UPDATE_UNLOCK_WITHOUT_LOCK 5 + +/* + * This is the PlatformRtMechanism opregion space handler. + * @function: indicates the read/write. In fact as the PlatformRtMechanism + * message is driven by command, only write is meaningful. + * + * @addr : not used + * @bits : not used. + * @value : it is an in/out parameter. It points to the PRM message buffer. + * @handler_context: not used + */ +static acpi_status acpi_platformrt_space_handler(u32 function, + acpi_physical_address addr, + u32 bits, acpi_integer *value, + void *handler_context, + void *region_context) +{ + struct prm_buffer *buffer = ACPI_CAST_PTR(struct prm_buffer, value); + struct prm_handler_info *handler; + struct prm_module_info *module; + efi_status_t status; + struct prm_context_buffer context; + + /* + * The returned acpi_status will always be AE_OK. Error values will be + * saved in the first byte of the PRM message buffer to be used by ASL. + */ + switch (buffer->prm_cmd) { + case PRM_CMD_RUN_SERVICE: + + handler = find_prm_handler(&buffer->handler_guid); + module = find_prm_module(&buffer->handler_guid); + if (!handler || !module) + goto invalid_guid; + + ACPI_COPY_NAMESEG(context.signature, "PRMC"); + context.revision = 0x0; + context.reserved = 0x0; + context.identifier = handler->guid; + context.static_data_buffer = handler->static_data_buffer_addr; + context.mmio_ranges = module->mmio_info; + + status = efi_call_virt_pointer(handler, handler_addr, + handler->acpi_param_buffer_addr, + &context); + if (status == EFI_SUCCESS) { + buffer->prm_status = PRM_HANDLER_SUCCESS; + } else { + buffer->prm_status = PRM_HANDLER_ERROR; + buffer->efi_status = status; + } + break; + + case PRM_CMD_START_TRANSACTION: + + module = find_prm_module(&buffer->handler_guid); + if (!module) + goto invalid_guid; + + if (module->updatable) + module->updatable = false; + else + buffer->prm_status = UPDATE_LOCK_ALREADY_HELD; + break; + + case PRM_CMD_END_TRANSACTION: + + module = find_prm_module(&buffer->handler_guid); + if (!module) + goto invalid_guid; + + if (module->updatable) + buffer->prm_status = UPDATE_UNLOCK_WITHOUT_LOCK; + else + module->updatable = true; + break; + + default: + + buffer->prm_status = INVALID_PRM_COMMAND; + break; + } + + return AE_OK; + +invalid_guid: + buffer->prm_status = PRM_HANDLER_GUID_NOT_FOUND; + return AE_OK; +} + +void __init init_prmt(void) +{ + acpi_status status; + int mc = acpi_table_parse_entries(ACPI_SIG_PRMT, sizeof(struct acpi_table_prmt), + 0, acpi_parse_prmt, 0); + pr_info("PRM: found %u modules\n", mc); + + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_PLATFORM_RT, + &acpi_platformrt_space_handler, + NULL, NULL); + if (ACPI_FAILURE(status)) + pr_alert("PRM: OperationRegion handler could not be installed\n"); +} diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index e48690a006a4..69a03d70740c 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -39,6 +39,7 @@ static int acpi_apic_instance __initdata; enum acpi_subtable_type { ACPI_SUBTABLE_COMMON, ACPI_SUBTABLE_HMAT, + ACPI_SUBTABLE_PRMT, }; struct acpi_subtable_entry { @@ -222,6 +223,8 @@ acpi_get_entry_type(struct acpi_subtable_entry *entry) return entry->hdr->common.type; case ACPI_SUBTABLE_HMAT: return entry->hdr->hmat.type; + case ACPI_SUBTABLE_PRMT: + return 0; } return 0; } @@ -234,6 +237,8 @@ acpi_get_entry_length(struct acpi_subtable_entry *entry) return entry->hdr->common.length; case ACPI_SUBTABLE_HMAT: return entry->hdr->hmat.length; + case ACPI_SUBTABLE_PRMT: + return entry->hdr->prmt.length; } return 0; } @@ -246,6 +251,8 @@ acpi_get_subtable_header_length(struct acpi_subtable_entry *entry) return sizeof(entry->hdr->common); case ACPI_SUBTABLE_HMAT: return sizeof(entry->hdr->hmat); + case ACPI_SUBTABLE_PRMT: + return sizeof(entry->hdr->prmt); } return 0; } @@ -255,6 +262,8 @@ acpi_get_subtable_type(char *id) { if (strncmp(id, ACPI_SIG_HMAT, 4) == 0) return ACPI_SUBTABLE_HMAT; + if (strncmp(id, ACPI_SIG_PRMT, 4) == 0) + return ACPI_SUBTABLE_PRMT; return ACPI_SUBTABLE_COMMON; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9f432411e988..6868b342cdc3 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -132,6 +132,7 @@ enum acpi_address_range_id { union acpi_subtable_headers { struct acpi_subtable_header common; struct acpi_hmat_structure hmat; + struct acpi_prmt_module_header prmt; }; typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table); diff --git a/include/linux/prmt.h b/include/linux/prmt.h new file mode 100644 index 000000000000..24da8364b919 --- /dev/null +++ b/include/linux/prmt.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifdef CONFIG_ACPI_PRMT +void init_prmt(void); +#else +static inline void init_prmt(void) { } +#endif From patchwork Mon Mar 22 22:37:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Erik Kaneda X-Patchwork-Id: 407001 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5F139C433C1 for ; Mon, 22 Mar 2021 23:10:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2286861879 for ; Mon, 22 Mar 2021 23:10:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230095AbhCVXKL (ORCPT ); Mon, 22 Mar 2021 19:10:11 -0400 Received: from mga06.intel.com ([134.134.136.31]:20269 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230298AbhCVXJk (ORCPT ); Mon, 22 Mar 2021 19:09:40 -0400 IronPort-SDR: lsvopVouV+Mi/NPi0e64EXy6g3IHUDBwhoIU//aienKUclCDmLK13XtWFSSKyrnB6CvCvh4o6s vg2vGsYHafTw== X-IronPort-AV: E=McAfee;i="6000,8403,9931"; a="251718885" X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="251718885" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Mar 2021 16:09:38 -0700 IronPort-SDR: GAIBKWqCD1B6lS0K3aBb4t8iJHQruKq4aUHwxf7pBfBGh2LjQmZAtBKhCK0/gFZmu2ajdzHEWQ +U69ZfzY7pYw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,269,1610438400"; d="scan'208";a="607510508" Received: from sibelius.jf.intel.com ([10.54.75.166]) by fmsmga005.fm.intel.com with ESMTP; 22 Mar 2021 16:09:38 -0700 From: Erik Kaneda To: "Rafael J . Wysocki" , ACPI Devel Maling List Cc: Erik Kaneda Subject: [PATCH v3 4/4] ACPI: Add \_SB._OSC bit for PRM Date: Mon, 22 Mar 2021 15:37:07 -0700 Message-Id: <20210322223707.1838823-5-erik.kaneda@intel.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210322223707.1838823-1-erik.kaneda@intel.com> References: <20210322223707.1838823-1-erik.kaneda@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Signed-off-by: Erik Kaneda --- drivers/acpi/bus.c | 1 + include/linux/acpi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 3484497923d5..e8119a9eca28 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -305,6 +305,7 @@ static void acpi_bus_osc_negotiate_platform_control(void) capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; + capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT; #ifdef CONFIG_ARM64 capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GENERIC_INITIATOR_SUPPORT; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 6868b342cdc3..fc50d2202446 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -547,6 +547,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); #define OSC_SB_OSLPI_SUPPORT 0x00000100 #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000 #define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000 +#define OSC_SB_PRM_SUPPORT 0x00020000 #define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000 extern bool osc_sb_apei_support_acked;