Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp694417pxb; Fri, 28 Jan 2022 08:07:12 -0800 (PST) X-Google-Smtp-Source: ABdhPJyoKWHa4/1gYjsvsUxILV+D8R4WoTlO/6L3JamNZyx8tcNEyCaijOoKwPRluwTqvBvRDhH/ X-Received: by 2002:a05:6402:2707:: with SMTP id y7mr8781656edd.329.1643386032472; Fri, 28 Jan 2022 08:07:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643386032; cv=none; d=google.com; s=arc-20160816; b=p5t10NQpG91jhZqMbnTDkDbUWCuoPsjuuLXCZhzgVjvcMb59StR4K9K2Mo6pO/QCqb KXBy4TusXilmSV8KcUaCpastgdhtDCoCVChe/CqnZ039QnWo/wd0QjGgNdD0lC3K3w6A Yl9No7tr91c/txyqg1p++uRmc5WSfGREKq3qh9TdU5h9UX6DfNlFT0Fre3L8aUogeI5Z 0O5EnWf9/UmRPGZ55LurGS+BStI5fZLgzO4pb3Z+pm8S8NfeSAavplznKJ+c71sm6QnB F5SxkLJiinV6VUyk3klv3Hmdx/XNYf8FsE/NLyttlbyBrsjlYTj7Qr3IzWtkIoWmz6cw MeRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature; bh=borUPHvIJgZompBcTudROyd9vC6KG8oScY7625cyHZQ=; b=LRNIq7bjBGz59yYKcsxCHJy9lbI1esleuBBaMdR3r3nuWUR2PRijChLPZGpPhJfJou h1o/WjDj82CAT4FGIP2WnYaVw6XwoZrYGb1LQjeS/Fm0nHzkRqf5NiQjhPu/NZALx/Cz SwR0toIF9zlY2DpDCJZfYoHB0uuIpbQ0g4p4vVxZF7GkqashaH2j+7MbJaH7Fr/u5Y5E qeME0BYdD3AUnU4cm6d+ROHRr7IpSSTnqWWHI9am6G+w3gsrjtS5DDxVTg1pjHKkq2y4 H+p4dcBr7s1RBbQS6mk6QUNiy0F4+YRDh9w/naaL5Yyomzt5A8WX4385+OFt7Nf2wJzk +Mng== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=X8s7xzS0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id qk37si4106437ejc.636.2022.01.28.08.06.47; Fri, 28 Jan 2022 08:07:12 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=X8s7xzS0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245574AbiA0TdH (ORCPT + 99 others); Thu, 27 Jan 2022 14:33:07 -0500 Received: from mga04.intel.com ([192.55.52.120]:47240 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245560AbiA0TdF (ORCPT ); Thu, 27 Jan 2022 14:33:05 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1643311985; x=1674847985; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=5wxokCeHr3CZMcEF/2Zw2aXPKU17FqMdEWEhikX7TrE=; b=X8s7xzS0FIFva8V6Ntl5/0wCgzxrRG5BbagK4v+ad+u/7C19ElGvQK/x Vl98RhrFcygZE9qWTRbcAdZqAyf2p6qEQirZf/6IriaCQfSYwmfADk9UU KCfXnFNVPnskoHELisYZZZXRk+7JzjsSZNUWAAQx3xsw3y0b+/vWSN7oi qs77cWmB3yDgR4HvlDA5VUg6rQTR0zAfU3Zn0AEL2Jwat6veA5JGjenT3 YWRpQhEobImGkAYGVVYIUhxPiPU4DAPg8kDOvaMBzeJfzaZZATyFgNwzK CPM6TuXJZ19AN+Wi09F3IvFTER4OzQ/WlS0Vg3ce2vuYFygKm5kH4wxgS A==; X-IronPort-AV: E=McAfee;i="6200,9189,10239"; a="245788386" X-IronPort-AV: E=Sophos;i="5.88,321,1635231600"; d="scan'208";a="245788386" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jan 2022 11:33:04 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.88,321,1635231600"; d="scan'208";a="495844905" Received: from ranerica-svr.sc.intel.com ([172.25.110.23]) by orsmga002.jf.intel.com with ESMTP; 27 Jan 2022 11:33:03 -0800 From: Ricardo Neri To: "Rafael J. Wysocki" , Daniel Lezcano , linux-pm@vger.kernel.org Cc: x86@kernel.org, linux-doc@vger.kernel.org, Len Brown , Srinivas Pandruvada , Aubrey Li , Amit Kucheria , Andi Kleen , Tim Chen , Lukasz Luba , "Ravi V. Shankar" , Ricardo Neri , linux-kernel@vger.kernel.org, Ricardo Neri Subject: [PATCH v5 3/7] thermal: intel: hfi: Minimally initialize the Hardware Feedback Interface Date: Thu, 27 Jan 2022 11:34:50 -0800 Message-Id: <20220127193454.12814-4-ricardo.neri-calderon@linux.intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220127193454.12814-1-ricardo.neri-calderon@linux.intel.com> References: <20220127193454.12814-1-ricardo.neri-calderon@linux.intel.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The Intel Hardware Feedback Interface provides guidance to the operating system about the performance and energy efficiency capabilities of each CPU in the system. Capabilities are numbers between 0 and 255 where a higher number represents a higher capability. For each CPU, energy efficiency and performance are reported as separate capabilities. Hardware computes these capabilities based on the operating conditions of the system such as power and thermal limits. These capabilities are shared with the operating system in a table resident in memory. Each package in the system has its own HFI instance. Every logical CPU in the package is represented in the table. More than one logical CPUs may be represented in a single table entry. When the hardware updates the table, it generates a package-level thermal interrupt. The size and format of the HFI table depend on the supported features and can only be determined at runtime. To minimally initialize the HFI, parse its features and allocate one instance per package of a data structure with the necessary parameters to read and navigate a local copy (i.e., owned by the driver) of individual HFI tables. A subsequent changeset will provide per-CPU initialization and interrupt handling. Cc: Andi Kleen Cc: Aubrey Li Cc: Srinivas Pandruvada Cc: Tim Chen Cc: "Ravi V. Shankar" Reviewed-by: Len Brown Co-developed by: Aubrey Li Signed-off-by: Aubrey Li Signed-off-by: Ricardo Neri --- Changes since v4: * Reworded description hfi_instance::hdr and hfi_instance::data. (Srinivas) Changes since v3: * None Changes since v2: * Rename the INTEL_HFI Kconfig option as INTEL_HFI_THERMAL to reflect better the nature of the feature. (Rafael) * Added missing #include files. Changes since v1: * Renamed X86_FEATURE_INTEL_HFI as X86_FEATURE_HFI. (Boris) * Reworked parsing of HFI features using bitfields instead of bitmasks. (PeterZ). * Removed hfi_instance::parsed as hfi_parse_features() is called only once via intel_hfi_init() via thermal_throttle_init_device(). (Rafael) * Converted pr_err() to pr_debug(). (Srinivas, Rafael) * Removed unnecessary dependency on CONFIG_SCHED_MC. * Renamed hfi_instance::ts_counter as hfi_instance::timestamp. * Renamed hfi_instance::table_base as hfi_instance::local_table and relocated its definition to this patch. * Wrapped hfi_instance::timestamp and hfi_instance:local_table in an anonymous union, since both point at the same location. --- drivers/thermal/intel/Kconfig | 12 ++ drivers/thermal/intel/Makefile | 1 + drivers/thermal/intel/intel_hfi.c | 181 ++++++++++++++++++++++++++++ drivers/thermal/intel/intel_hfi.h | 11 ++ drivers/thermal/intel/therm_throt.c | 3 + 5 files changed, 208 insertions(+) create mode 100644 drivers/thermal/intel/intel_hfi.c create mode 100644 drivers/thermal/intel/intel_hfi.h diff --git a/drivers/thermal/intel/Kconfig b/drivers/thermal/intel/Kconfig index c83ea5d04a1d..e9d2925227d4 100644 --- a/drivers/thermal/intel/Kconfig +++ b/drivers/thermal/intel/Kconfig @@ -99,3 +99,15 @@ config INTEL_MENLOW Intel Menlow platform. If unsure, say N. + +config INTEL_HFI_THERMAL + bool "Intel Hardware Feedback Interface" + depends on CPU_SUP_INTEL + depends on X86_THERMAL_VECTOR + help + Select this option to enable the Hardware Feedback Interface. If + selected, hardware provides guidance to the operating system on + the performance and energy efficiency capabilities of each CPU. + These capabilities may change as a result of changes in the operating + conditions of the system such power and thermal limits. If selected, + the kernel relays updates in CPUs' capabilities to userspace. diff --git a/drivers/thermal/intel/Makefile b/drivers/thermal/intel/Makefile index 960b56268b4a..9a8d8054f316 100644 --- a/drivers/thermal/intel/Makefile +++ b/drivers/thermal/intel/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o obj-$(CONFIG_INTEL_TCC_COOLING) += intel_tcc_cooling.o obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o +obj-$(CONFIG_INTEL_HFI_THERMAL) += intel_hfi.o diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c new file mode 100644 index 000000000000..969f4a150973 --- /dev/null +++ b/drivers/thermal/intel/intel_hfi.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Hardware Feedback Interface Driver + * + * Copyright (c) 2021, Intel Corporation. + * + * Authors: Aubrey Li + * Ricardo Neri + * + * + * The Hardware Feedback Interface provides a performance and energy efficiency + * capability information for each CPU in the system. Depending on the processor + * model, hardware may periodically update these capabilities as a result of + * changes in the operating conditions (e.g., power limits or thermal + * constraints). On other processor models, there is a single HFI update + * at boot. + * + * This file provides functionality to process HFI updates and relay these + * updates to userspace. + */ + +#define pr_fmt(fmt) "intel-hfi: " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include "intel_hfi.h" + +/* CPUID detection and enumeration definitions for HFI */ + +#define CPUID_HFI_LEAF 6 + +union hfi_capabilities { + struct { + u8 performance:1; + u8 energy_efficiency:1; + u8 __reserved:6; + } split; + u8 bits; +}; + +union cpuid6_edx { + struct { + union hfi_capabilities capabilities; + u32 table_pages:4; + u32 __reserved:4; + s32 index:16; + } split; + u32 full; +}; + +/** + * struct hfi_cpu_data - HFI capabilities per CPU + * @perf_cap: Performance capability + * @ee_cap: Energy efficiency capability + * + * Capabilities of a logical processor in the HFI table. These capabilities are + * unitless. + */ +struct hfi_cpu_data { + u8 perf_cap; + u8 ee_cap; +} __packed; + +/** + * struct hfi_hdr - Header of the HFI table + * @perf_updated: Hardware updated performance capabilities + * @ee_updated: Hardware updated energy efficiency capabilities + * + * Properties of the data in an HFI table. + */ +struct hfi_hdr { + u8 perf_updated; + u8 ee_updated; +} __packed; + +/** + * struct hfi_instance - Representation of an HFI instance (i.e., a table) + * @local_table: Base of the local copy of the HFI table + * @timestamp: Timestamp of the last update of the local table. + * Located at the base of the local table. + * @hdr: Base address of the header of the local table + * @data: Base address of the data of the local table + * + * A set of parameters to parse and navigate a specific HFI table. + */ +struct hfi_instance { + union { + void *local_table; + u64 *timestamp; + }; + void *hdr; + void *data; +}; + +/** + * struct hfi_features - Supported HFI features + * @nr_table_pages: Size of the HFI table in 4KB pages + * @cpu_stride: Stride size to locate the capability data of a logical + * processor within the table (i.e., row stride) + * @hdr_size: Size of the table header + * + * Parameters and supported features that are common to all HFI instances + */ +struct hfi_features { + unsigned int nr_table_pages; + unsigned int cpu_stride; + unsigned int hdr_size; +}; + +static int max_hfi_instances; +static struct hfi_instance *hfi_instances; + +static struct hfi_features hfi_features; + +static __init int hfi_parse_features(void) +{ + unsigned int nr_capabilities; + union cpuid6_edx edx; + + if (!boot_cpu_has(X86_FEATURE_HFI)) + return -ENODEV; + + /* + * If we are here we know that CPUID_HFI_LEAF exists. Parse the + * supported capabilities and the size of the HFI table. + */ + edx.full = cpuid_edx(CPUID_HFI_LEAF); + + if (!edx.split.capabilities.split.performance) { + pr_debug("Performance reporting not supported! Not using HFI\n"); + return -ENODEV; + } + + /* + * The number of supported capabilities determines the number of + * columns in the HFI table. Exclude the reserved bits. + */ + edx.split.capabilities.split.__reserved = 0; + nr_capabilities = hweight8(edx.split.capabilities.bits); + + /* The number of 4KB pages required by the table */ + hfi_features.nr_table_pages = edx.split.table_pages + 1; + + /* + * The header contains change indications for each supported feature. + * The size of the table header is rounded up to be a multiple of 8 + * bytes. + */ + hfi_features.hdr_size = DIV_ROUND_UP(nr_capabilities, 8) * 8; + + /* + * Data of each logical processor is also rounded up to be a multiple + * of 8 bytes. + */ + hfi_features.cpu_stride = DIV_ROUND_UP(nr_capabilities, 8) * 8; + + return 0; +} + +void __init intel_hfi_init(void) +{ + if (hfi_parse_features()) + return; + + /* There is one HFI instance per die/package. */ + max_hfi_instances = topology_max_packages() * + topology_max_die_per_package(); + + /* + * This allocation may fail. CPU hotplug callbacks must check + * for a null pointer. + */ + hfi_instances = kcalloc(max_hfi_instances, sizeof(*hfi_instances), + GFP_KERNEL); +} diff --git a/drivers/thermal/intel/intel_hfi.h b/drivers/thermal/intel/intel_hfi.h new file mode 100644 index 000000000000..05f748b48a4e --- /dev/null +++ b/drivers/thermal/intel/intel_hfi.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _INTEL_HFI_H +#define _INTEL_HFI_H + +#if defined(CONFIG_INTEL_HFI_THERMAL) +void __init intel_hfi_init(void); +#else +static inline void intel_hfi_init(void) { } +#endif /* CONFIG_INTEL_HFI_THERMAL */ + +#endif /* _INTEL_HFI_H */ diff --git a/drivers/thermal/intel/therm_throt.c b/drivers/thermal/intel/therm_throt.c index dab7e8fb1059..ac408714d52b 100644 --- a/drivers/thermal/intel/therm_throt.c +++ b/drivers/thermal/intel/therm_throt.c @@ -32,6 +32,7 @@ #include #include +#include "intel_hfi.h" #include "thermal_interrupt.h" /* How long to wait between reporting thermal events */ @@ -509,6 +510,8 @@ static __init int thermal_throttle_init_device(void) if (!atomic_read(&therm_throt_en)) return 0; + intel_hfi_init(); + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/therm:online", thermal_throttle_online, thermal_throttle_offline); -- 2.17.1