1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Hardware Feedback Interface Driver 4 * 5 * Copyright (c) 2021, Intel Corporation. 6 * 7 * Authors: Aubrey Li <aubrey.li@linux.intel.com> 8 * Ricardo Neri <ricardo.neri-calderon@linux.intel.com> 9 * 10 * 11 * The Hardware Feedback Interface provides a performance and energy efficiency 12 * capability information for each CPU in the system. Depending on the processor 13 * model, hardware may periodically update these capabilities as a result of 14 * changes in the operating conditions (e.g., power limits or thermal 15 * constraints). On other processor models, there is a single HFI update 16 * at boot. 17 * 18 * This file provides functionality to process HFI updates and relay these 19 * updates to userspace. 20 */ 21 22 #define pr_fmt(fmt) "intel-hfi: " fmt 23 24 #include <linux/bitops.h> 25 #include <linux/cpufeature.h> 26 #include <linux/math.h> 27 #include <linux/printk.h> 28 #include <linux/processor.h> 29 #include <linux/slab.h> 30 #include <linux/topology.h> 31 32 #include "intel_hfi.h" 33 34 /* CPUID detection and enumeration definitions for HFI */ 35 36 #define CPUID_HFI_LEAF 6 37 38 union hfi_capabilities { 39 struct { 40 u8 performance:1; 41 u8 energy_efficiency:1; 42 u8 __reserved:6; 43 } split; 44 u8 bits; 45 }; 46 47 union cpuid6_edx { 48 struct { 49 union hfi_capabilities capabilities; 50 u32 table_pages:4; 51 u32 __reserved:4; 52 s32 index:16; 53 } split; 54 u32 full; 55 }; 56 57 /** 58 * struct hfi_cpu_data - HFI capabilities per CPU 59 * @perf_cap: Performance capability 60 * @ee_cap: Energy efficiency capability 61 * 62 * Capabilities of a logical processor in the HFI table. These capabilities are 63 * unitless. 64 */ 65 struct hfi_cpu_data { 66 u8 perf_cap; 67 u8 ee_cap; 68 } __packed; 69 70 /** 71 * struct hfi_hdr - Header of the HFI table 72 * @perf_updated: Hardware updated performance capabilities 73 * @ee_updated: Hardware updated energy efficiency capabilities 74 * 75 * Properties of the data in an HFI table. 76 */ 77 struct hfi_hdr { 78 u8 perf_updated; 79 u8 ee_updated; 80 } __packed; 81 82 /** 83 * struct hfi_instance - Representation of an HFI instance (i.e., a table) 84 * @local_table: Base of the local copy of the HFI table 85 * @timestamp: Timestamp of the last update of the local table. 86 * Located at the base of the local table. 87 * @hdr: Base address of the header of the local table 88 * @data: Base address of the data of the local table 89 * 90 * A set of parameters to parse and navigate a specific HFI table. 91 */ 92 struct hfi_instance { 93 union { 94 void *local_table; 95 u64 *timestamp; 96 }; 97 void *hdr; 98 void *data; 99 }; 100 101 /** 102 * struct hfi_features - Supported HFI features 103 * @nr_table_pages: Size of the HFI table in 4KB pages 104 * @cpu_stride: Stride size to locate the capability data of a logical 105 * processor within the table (i.e., row stride) 106 * @hdr_size: Size of the table header 107 * 108 * Parameters and supported features that are common to all HFI instances 109 */ 110 struct hfi_features { 111 unsigned int nr_table_pages; 112 unsigned int cpu_stride; 113 unsigned int hdr_size; 114 }; 115 116 static int max_hfi_instances; 117 static struct hfi_instance *hfi_instances; 118 119 static struct hfi_features hfi_features; 120 121 static __init int hfi_parse_features(void) 122 { 123 unsigned int nr_capabilities; 124 union cpuid6_edx edx; 125 126 if (!boot_cpu_has(X86_FEATURE_HFI)) 127 return -ENODEV; 128 129 /* 130 * If we are here we know that CPUID_HFI_LEAF exists. Parse the 131 * supported capabilities and the size of the HFI table. 132 */ 133 edx.full = cpuid_edx(CPUID_HFI_LEAF); 134 135 if (!edx.split.capabilities.split.performance) { 136 pr_debug("Performance reporting not supported! Not using HFI\n"); 137 return -ENODEV; 138 } 139 140 /* 141 * The number of supported capabilities determines the number of 142 * columns in the HFI table. Exclude the reserved bits. 143 */ 144 edx.split.capabilities.split.__reserved = 0; 145 nr_capabilities = hweight8(edx.split.capabilities.bits); 146 147 /* The number of 4KB pages required by the table */ 148 hfi_features.nr_table_pages = edx.split.table_pages + 1; 149 150 /* 151 * The header contains change indications for each supported feature. 152 * The size of the table header is rounded up to be a multiple of 8 153 * bytes. 154 */ 155 hfi_features.hdr_size = DIV_ROUND_UP(nr_capabilities, 8) * 8; 156 157 /* 158 * Data of each logical processor is also rounded up to be a multiple 159 * of 8 bytes. 160 */ 161 hfi_features.cpu_stride = DIV_ROUND_UP(nr_capabilities, 8) * 8; 162 163 return 0; 164 } 165 166 void __init intel_hfi_init(void) 167 { 168 if (hfi_parse_features()) 169 return; 170 171 /* There is one HFI instance per die/package. */ 172 max_hfi_instances = topology_max_packages() * 173 topology_max_die_per_package(); 174 175 /* 176 * This allocation may fail. CPU hotplug callbacks must check 177 * for a null pointer. 178 */ 179 hfi_instances = kcalloc(max_hfi_instances, sizeof(*hfi_instances), 180 GFP_KERNEL); 181 } 182