diff --git a/patches/0001-cachyos-base-all.patch b/patches/0001-cachyos-base-all.patch index 3368db0..cb5cb43 100644 --- a/patches/0001-cachyos-base-all.patch +++ b/patches/0001-cachyos-base-all.patch @@ -1,7 +1,7 @@ -From 9098cf37fa8cdba73fd27f71e6455f6b65161414 Mon Sep 17 00:00:00 2001 +From 5984a6b2cf95450f2f92610cfb69378b844da2a6 Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:51:09 +0800 -Subject: [PATCH 01/14] address-masking +Subject: [PATCH 01/13] address-masking Signed-off-by: Eric Naim --- @@ -108,12 +108,12 @@ index feeb935a2299..6e489f9e90f1 100644 src_addr = (unsigned long)untagged_addr(str); if (likely(src_addr < max_addr)) { -- -2.47.0 +2.47.0.rc0 -From c02337bbd9d3afc905a664fd4515f01d81a5b853 Mon Sep 17 00:00:00 2001 +From bd40ee69b53e1cb291f96d3ad1120698aea8e96b Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:51:22 +0800 -Subject: [PATCH 02/14] amd-cache-optimizer +Subject: [PATCH 02/13] amd-cache-optimizer Signed-off-by: Eric Naim --- @@ -401,23 +401,32 @@ index 000000000000..679613d02b9a +MODULE_DESCRIPTION("AMD 3D V-Cache Performance Optimizer Driver"); +MODULE_LICENSE("GPL"); -- -2.47.0 +2.47.0.rc0 -From 7d73843d2171a47e4934180bf94ad1c6d615fc15 Mon Sep 17 00:00:00 2001 -From: Eric Naim -Date: Tue, 22 Oct 2024 22:51:35 +0800 -Subject: [PATCH 03/14] amd-pstate +From f6f25468febfb80b968b50dabfb3f5656c4524e8 Mon Sep 17 00:00:00 2001 +From: Peter Jung +Date: Fri, 25 Oct 2024 18:38:55 +0200 +Subject: [PATCH 03/13] amd-pstate -Signed-off-by: Eric Naim +Signed-off-by: Peter Jung --- Documentation/admin-guide/pm/amd-pstate.rst | 15 +- - arch/x86/include/asm/processor.h | 3 - - arch/x86/kernel/acpi/cppc.c | 172 ++++++++++++- + arch/x86/include/asm/cpufeatures.h | 3 +- + arch/x86/include/asm/intel-family.h | 6 + + arch/x86/include/asm/processor.h | 21 +- + arch/x86/include/asm/topology.h | 9 + + arch/x86/kernel/acpi/cppc.c | 195 +++++++++++++- arch/x86/kernel/cpu/amd.c | 16 -- + arch/x86/kernel/cpu/debugfs.c | 1 + + arch/x86/kernel/cpu/scattered.c | 3 +- + arch/x86/kernel/cpu/topology_amd.c | 3 + + arch/x86/kernel/cpu/topology_common.c | 34 +++ + arch/x86/kernel/smpboot.c | 5 +- drivers/cpufreq/acpi-cpufreq.c | 12 +- - drivers/cpufreq/amd-pstate.c | 263 +++++++------------- + drivers/cpufreq/amd-pstate.c | 265 +++++++------------- include/acpi/cppc_acpi.h | 41 ++- - 7 files changed, 298 insertions(+), 224 deletions(-) + tools/arch/x86/include/asm/cpufeatures.h | 2 +- + 16 files changed, 401 insertions(+), 230 deletions(-) diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst index d0324d44f548..210a808b74ec 100644 @@ -452,11 +461,65 @@ index d0324d44f548..210a808b74ec 100644 ``energy_performance_available_preferences`` A list of all the supported EPP preferences that could be used for +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +index 913fd3a7bac6..51b38bc66796 100644 +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -473,7 +473,8 @@ + #define X86_FEATURE_BHI_CTRL (21*32+ 2) /* BHI_DIS_S HW control available */ + #define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* BHI_DIS_S HW control enabled */ + #define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* Clear branch history at vmexit using SW loop */ +-#define X86_FEATURE_FAST_CPPC (21*32 + 5) /* AMD Fast CPPC */ ++#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */ ++#define X86_FEATURE_AMD_HETEROGENEOUS_CORES (21*32 + 6) /* Heterogeneous Core Topology */ + + /* + * BUG word(s) +diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h +index f81a851c46dc..a44a3e026c4f 100644 +--- a/arch/x86/include/asm/intel-family.h ++++ b/arch/x86/include/asm/intel-family.h +@@ -257,4 +257,10 @@ + #define INTEL_FAM5_QUARK_X1000 0x09 /* Quark X1000 SoC */ + #define INTEL_QUARK_X1000 IFM(5, 0x09) /* Quark X1000 SoC */ + ++/* CPU core types */ ++enum intel_cpu_type { ++ INTEL_CPU_TYPE_ATOM = 0x20, ++ INTEL_CPU_TYPE_CORE = 0x40, ++}; ++ + #endif /* _ASM_X86_INTEL_FAMILY_H */ diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h -index a75a07f4931f..775acbdea1a9 100644 +index a75a07f4931f..e17f4d733e44 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h -@@ -691,8 +691,6 @@ static inline u32 per_cpu_l2c_id(unsigned int cpu) +@@ -105,6 +105,24 @@ struct cpuinfo_topology { + // Cache level topology IDs + u32 llc_id; + u32 l2c_id; ++ ++ // Hardware defined CPU-type ++ union { ++ u32 cpu_type; ++ struct { ++ // CPUID.1A.EAX[23-0] ++ u32 intel_native_model_id :24; ++ // CPUID.1A.EAX[31-24] ++ u32 intel_type :8; ++ }; ++ struct { ++ // CPUID 0x80000026.EBX ++ u32 amd_num_processors :16, ++ amd_power_eff_ranking :8, ++ amd_native_model_id :4, ++ amd_type :4; ++ }; ++ }; + }; + + struct cpuinfo_x86 { +@@ -691,8 +709,6 @@ static inline u32 per_cpu_l2c_id(unsigned int cpu) } #ifdef CONFIG_CPU_SUP_AMD @@ -465,7 +528,7 @@ index a75a07f4931f..775acbdea1a9 100644 /* * Issue a DIV 0/1 insn to clear any division data from previous DIV * operations. -@@ -705,7 +703,6 @@ static __always_inline void amd_clear_divider(void) +@@ -705,7 +721,6 @@ static __always_inline void amd_clear_divider(void) extern void amd_check_microcode(void); #else @@ -473,8 +536,35 @@ index a75a07f4931f..775acbdea1a9 100644 static inline void amd_clear_divider(void) { } static inline void amd_check_microcode(void) { } #endif +diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h +index abe3a8f22cbd..94d9832a5bc8 100644 +--- a/arch/x86/include/asm/topology.h ++++ b/arch/x86/include/asm/topology.h +@@ -114,6 +114,12 @@ enum x86_topology_domains { + TOPO_MAX_DOMAIN, + }; + ++enum x86_topology_cpu_type { ++ TOPO_CPU_TYPE_PERFORMANCE, ++ TOPO_CPU_TYPE_EFFICIENCY, ++ TOPO_CPU_TYPE_UNKNOWN, ++}; ++ + struct x86_topology_system { + unsigned int dom_shifts[TOPO_MAX_DOMAIN]; + unsigned int dom_size[TOPO_MAX_DOMAIN]; +@@ -149,6 +155,9 @@ extern unsigned int __max_threads_per_core; + extern unsigned int __num_threads_per_package; + extern unsigned int __num_cores_per_package; + ++const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c); ++enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c); ++ + static inline unsigned int topology_max_packages(void) + { + return __max_logical_packages; diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c -index ff8f25faca3d..956984054bf3 100644 +index ff8f25faca3d..59edf64ad9ed 100644 --- a/arch/x86/kernel/acpi/cppc.c +++ b/arch/x86/kernel/acpi/cppc.c @@ -9,6 +9,17 @@ @@ -537,7 +627,7 @@ index ff8f25faca3d..956984054bf3 100644 freq_invariance_set_perf_ratio(perf_ratio, false); } -@@ -116,3 +126,143 @@ void init_freq_invariance_cppc(void) +@@ -116,3 +126,166 @@ void init_freq_invariance_cppc(void) init_done = true; mutex_unlock(&freq_invariance_lock); } @@ -649,8 +739,10 @@ index ff8f25faca3d..956984054bf3 100644 + */ +int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) +{ ++ enum x86_topology_cpu_type core_type = get_topology_cpu_type(&cpu_data(cpu)); + bool prefcore; + int ret; ++ u32 tmp; + + ret = amd_detect_prefcore(&prefcore); + if (ret) @@ -676,6 +768,27 @@ index ff8f25faca3d..956984054bf3 100644 + break; + } + } ++ ++ /* detect if running on heterogeneous design */ ++ if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) { ++ switch (core_type) { ++ case TOPO_CPU_TYPE_UNKNOWN: ++ pr_warn("Undefined core type found for cpu %d\n", cpu); ++ break; ++ case TOPO_CPU_TYPE_PERFORMANCE: ++ /* use the max scale for performance cores */ ++ *numerator = CPPC_HIGHEST_PERF_PERFORMANCE; ++ return 0; ++ case TOPO_CPU_TYPE_EFFICIENCY: ++ /* use the highest perf value for efficiency cores */ ++ ret = amd_get_highest_perf(cpu, &tmp); ++ if (ret) ++ return ret; ++ *numerator = tmp; ++ return 0; ++ } ++ } ++ + *numerator = CPPC_HIGHEST_PERF_PREFCORE; + + return 0; @@ -708,6 +821,134 @@ index f01b72052f79..fab5caec0b72 100644 static void zenbleed_check_cpu(void *unused) { struct cpuinfo_x86 *c = &cpu_data(smp_processor_id()); +diff --git a/arch/x86/kernel/cpu/debugfs.c b/arch/x86/kernel/cpu/debugfs.c +index 3baf3e435834..10719aba6276 100644 +--- a/arch/x86/kernel/cpu/debugfs.c ++++ b/arch/x86/kernel/cpu/debugfs.c +@@ -22,6 +22,7 @@ static int cpu_debug_show(struct seq_file *m, void *p) + seq_printf(m, "die_id: %u\n", c->topo.die_id); + seq_printf(m, "cu_id: %u\n", c->topo.cu_id); + seq_printf(m, "core_id: %u\n", c->topo.core_id); ++ seq_printf(m, "cpu_type: %s\n", get_topology_cpu_type_name(c)); + seq_printf(m, "logical_pkg_id: %u\n", c->topo.logical_pkg_id); + seq_printf(m, "logical_die_id: %u\n", c->topo.logical_die_id); + seq_printf(m, "llc_id: %u\n", c->topo.llc_id); +diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c +index c84c30188fdf..307a91741534 100644 +--- a/arch/x86/kernel/cpu/scattered.c ++++ b/arch/x86/kernel/cpu/scattered.c +@@ -45,13 +45,14 @@ static const struct cpuid_bit cpuid_bits[] = { + { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, + { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, + { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, +- { X86_FEATURE_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, ++ { X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, + { X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 }, + { X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 }, + { X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 }, + { X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 }, + { X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 }, + { X86_FEATURE_AMD_LBR_PMC_FREEZE, CPUID_EAX, 2, 0x80000022, 0 }, ++ { X86_FEATURE_AMD_HETEROGENEOUS_CORES, CPUID_EAX, 30, 0x80000026, 0 }, + { 0, 0, 0, 0, 0 } + }; + +diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c +index 7d476fa697ca..03b3c9c3a45e 100644 +--- a/arch/x86/kernel/cpu/topology_amd.c ++++ b/arch/x86/kernel/cpu/topology_amd.c +@@ -182,6 +182,9 @@ static void parse_topology_amd(struct topo_scan *tscan) + if (cpu_feature_enabled(X86_FEATURE_TOPOEXT)) + has_topoext = cpu_parse_topology_ext(tscan); + ++ if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) ++ tscan->c->topo.cpu_type = cpuid_ebx(0x80000026); ++ + if (!has_topoext && !parse_8000_0008(tscan)) + return; + +diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/topology_common.c +index 9a6069e7133c..8277c64f88db 100644 +--- a/arch/x86/kernel/cpu/topology_common.c ++++ b/arch/x86/kernel/cpu/topology_common.c +@@ -3,6 +3,7 @@ + + #include + ++#include + #include + #include + #include +@@ -27,6 +28,36 @@ void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains dom, + } + } + ++enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c) ++{ ++ if (c->x86_vendor == X86_VENDOR_INTEL) { ++ switch (c->topo.intel_type) { ++ case INTEL_CPU_TYPE_ATOM: return TOPO_CPU_TYPE_EFFICIENCY; ++ case INTEL_CPU_TYPE_CORE: return TOPO_CPU_TYPE_PERFORMANCE; ++ } ++ } ++ if (c->x86_vendor == X86_VENDOR_AMD) { ++ switch (c->topo.amd_type) { ++ case 0: return TOPO_CPU_TYPE_PERFORMANCE; ++ case 1: return TOPO_CPU_TYPE_EFFICIENCY; ++ } ++ } ++ ++ return TOPO_CPU_TYPE_UNKNOWN; ++} ++ ++const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c) ++{ ++ switch (get_topology_cpu_type(c)) { ++ case TOPO_CPU_TYPE_PERFORMANCE: ++ return "performance"; ++ case TOPO_CPU_TYPE_EFFICIENCY: ++ return "efficiency"; ++ default: ++ return "unknown"; ++ } ++} ++ + static unsigned int __maybe_unused parse_num_cores_legacy(struct cpuinfo_x86 *c) + { + struct { +@@ -87,6 +118,7 @@ static void parse_topology(struct topo_scan *tscan, bool early) + .cu_id = 0xff, + .llc_id = BAD_APICID, + .l2c_id = BAD_APICID, ++ .cpu_type = TOPO_CPU_TYPE_UNKNOWN, + }; + struct cpuinfo_x86 *c = tscan->c; + struct { +@@ -132,6 +164,8 @@ static void parse_topology(struct topo_scan *tscan, bool early) + case X86_VENDOR_INTEL: + if (!IS_ENABLED(CONFIG_CPU_SUP_INTEL) || !cpu_parse_topology_ext(tscan)) + parse_legacy(tscan); ++ if (c->cpuid_level >= 0x1a) ++ c->topo.cpu_type = cpuid_eax(0x1a); + break; + case X86_VENDOR_HYGON: + if (IS_ENABLED(CONFIG_CPU_SUP_HYGON)) +diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c +index 390e4fe7433e..9ee84f58f3b4 100644 +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -497,8 +497,9 @@ static int x86_cluster_flags(void) + + static int x86_die_flags(void) + { +- if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) +- return x86_sched_itmt_flags(); ++ if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU) || ++ cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) ++ return x86_sched_itmt_flags(); + + return 0; + } diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index a8ca625a98b8..0f04feb6cafa 100644 --- a/drivers/cpufreq/acpi-cpufreq.c @@ -733,7 +974,7 @@ index a8ca625a98b8..0f04feb6cafa 100644 nominal_perf = perf_caps.nominal_perf; diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c -index 589fde37ccd7..41965c49ec96 100644 +index 589fde37ccd7..fb0a72ccff79 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -52,8 +52,6 @@ @@ -1082,6 +1323,15 @@ index 589fde37ccd7..41965c49ec96 100644 WRITE_ONCE(cpudata->prefcore_ranking, cur_high); if (cur_high < CPPC_MAX_PERF) +@@ -924,7 +838,7 @@ static u32 amd_pstate_get_transition_delay_us(unsigned int cpu) + + transition_delay_ns = cppc_get_transition_latency(cpu); + if (transition_delay_ns == CPUFREQ_ETERNAL) { +- if (cpu_feature_enabled(X86_FEATURE_FAST_CPPC)) ++ if (cpu_feature_enabled(X86_FEATURE_AMD_FAST_CPPC)) + return AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY; + else + return AMD_PSTATE_TRANSITION_DELAY; @@ -962,8 +876,8 @@ static u32 amd_pstate_get_transition_latency(unsigned int cpu) static int amd_pstate_init_freq(struct amd_cpudata *cpudata) { @@ -1352,1288 +1602,6 @@ index e1720d930666..76e44e102780 100644 } #endif /* !CONFIG_ACPI_CPPC_LIB */ --- -2.47.0 - -From daabe6ab6f76dcfce8392317af98efdf21759aaf Mon Sep 17 00:00:00 2001 -From: Eric Naim -Date: Tue, 22 Oct 2024 23:38:09 +0800 -Subject: [PATCH 04/14] amd-hfi - -Signed-off-by: Eric Naim ---- - Documentation/arch/x86/amd-hfi.rst | 129 ++++++ - Documentation/arch/x86/index.rst | 1 + - MAINTAINERS | 9 + - arch/x86/include/asm/cpu.h | 19 + - arch/x86/include/asm/cpufeatures.h | 4 +- - arch/x86/include/asm/hreset.h | 6 + - arch/x86/include/asm/msr-index.h | 5 + - arch/x86/include/asm/processor.h | 18 + - arch/x86/include/asm/topology.h | 8 + - arch/x86/kernel/acpi/cppc.c | 23 + - arch/x86/kernel/cpu/amd.c | 14 + - arch/x86/kernel/cpu/common.c | 15 + - arch/x86/kernel/cpu/debugfs.c | 1 + - arch/x86/kernel/cpu/intel.c | 18 + - arch/x86/kernel/cpu/scattered.c | 4 +- - arch/x86/kernel/cpu/topology_amd.c | 3 + - arch/x86/kernel/cpu/topology_common.c | 13 + - arch/x86/kernel/process_32.c | 3 + - arch/x86/kernel/process_64.c | 3 + - arch/x86/kernel/smpboot.c | 5 +- - drivers/cpufreq/amd-pstate.c | 8 +- - drivers/platform/x86/amd/Kconfig | 1 + - drivers/platform/x86/amd/Makefile | 1 + - drivers/platform/x86/amd/hfi/Kconfig | 21 + - drivers/platform/x86/amd/hfi/Makefile | 7 + - drivers/platform/x86/amd/hfi/hfi.c | 547 +++++++++++++++++++++++ - tools/arch/x86/include/asm/cpufeatures.h | 2 +- - 27 files changed, 882 insertions(+), 6 deletions(-) - create mode 100644 Documentation/arch/x86/amd-hfi.rst - create mode 100644 arch/x86/include/asm/hreset.h - create mode 100644 drivers/platform/x86/amd/hfi/Kconfig - create mode 100644 drivers/platform/x86/amd/hfi/Makefile - create mode 100644 drivers/platform/x86/amd/hfi/hfi.c - -diff --git a/Documentation/arch/x86/amd-hfi.rst b/Documentation/arch/x86/amd-hfi.rst -new file mode 100644 -index 000000000000..b66ff083855f ---- /dev/null -+++ b/Documentation/arch/x86/amd-hfi.rst -@@ -0,0 +1,129 @@ -+.. SPDX-License-Identifier: GPL-2.0 -+ -+====================================================================== -+Hardware Feedback Interface For Hetero Core Scheduling On AMD Platform -+====================================================================== -+ -+:Copyright: 2024 Advanced Micro Devices, Inc. All Rights Reserved. -+ -+:Author: Perry Yuan -+:Author: Mario Limonciello -+ -+Overview -+-------- -+ -+AMD Heterogeneous Core implementations are comprised of more than one -+architectural class and CPUs are comprised of cores of various efficiency and -+power capabilities: performance-oriented *classic cores* and power-efficient -+*dense cores*. As such, power management strategies must be designed to -+accommodate the complexities introduced by incorporating different core types. -+Heterogeneous systems can also extend to more than two architectural classes as -+well. The purpose of the scheduling feedback mechanism is to provide -+information to the operating system scheduler in real time such that the -+scheduler can direct threads to the optimal core. -+ -+The goal of AMD's heterogeneous architecture is to attain power benefit by sending -+background thread to the dense cores while sending high priority threads to the classic -+cores. From a performance perspective, sending background threads to dense cores can free -+up power headroom and allow the classic cores to optimally service demanding threads. -+Furthermore, the area optimized nature of the dense cores allows for an increasing -+number of physical cores. This improved core density will have positive multithreaded -+performance impact. -+ -+AMD Heterogeneous Core Driver -+----------------------------- -+ -+The ``amd_hfi`` driver delivers the operating system a performance and energy efficiency -+capability data for each CPU in the system. The scheduler can use the ranking data -+from the HFI driver to make task placement decisions. -+ -+Thread Classification and Ranking Table Interaction -+---------------------------------------------------- -+ -+The thread classification is used to select into a ranking table that describes -+an efficiency and performance ranking for each classification. -+ -+Threads are classified during runtime into enumerated classes. The classes represent -+thread performance/power characteristics that may benefit from special scheduling behaviors. -+The below table depicts an example of thread classification and a preference where a given thread -+should be scheduled based on its thread class. The real time thread classification is consumed -+by the operating system and is used to inform the scheduler of where the thread should be placed. -+ -+Thread Classification Example Table -+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -++----------+----------------+-------------------------------+---------------------+---------+ -+| class ID | Classification | Preferred scheduling behavior | Preemption priority | Counter | -++----------+----------------+-------------------------------+---------------------+---------+ -+| 0 | Default | Performant | Highest | | -++----------+----------------+-------------------------------+---------------------+---------+ -+| 1 | Non-scalable | Efficient | Lowest | PMCx1A1 | -++----------+----------------+-------------------------------+---------------------+---------+ -+| 2 | I/O bound | Efficient | Lowest | PMCx044 | -++----------+----------------+-------------------------------+---------------------+---------+ -+ -+Thread classification is performed by the hardware each time that the thread is switched out. -+Threads that don't meet any hardware specified criteria will be classified as "default". -+ -+AMD Hardware Feedback Interface -+-------------------------------- -+ -+The Hardware Feedback Interface provides to the operating system information -+about the performance and energy efficiency of each CPU in the system. Each -+capability is given as a unit-less quantity in the range [0-255]. A higher -+performance value indicates higher performance capability, and a higher -+efficiency value indicates more efficiency. Energy efficiency and performance -+are reported in separate capabilities in the shared memory based ranking table. -+ -+These capabilities may change at runtime as a result of changes in the -+operating conditions of the system or the action of external factors. -+Power Management FW is responsible for detecting events that would require -+a reordering of the performance and efficiency ranking. Table updates would -+happen relatively infrequently and occur on the time scale of seconds or more. -+ -+The following events trigger a table update: -+ * Thermal Stress Events -+ * Silent Compute -+ * Extreme Low Battery Scenarios -+ -+The kernel or a userspace policy daemon can use these capabilities to modify -+task placement decisions. For instance, if either the performance or energy -+capabilities of a given logical processor becomes zero, it is an indication that -+the hardware recommends to the operating system to not schedule any tasks on -+that processor for performance or energy efficiency reasons, respectively. -+ -+Implementation details for Linux -+-------------------------------- -+ -+The implementation of threads scheduling consists of the following steps: -+ -+1. A thread is spawned and scheduled to the ideal core using the default -+ heterogeneous scheduling policy. -+2. The processor profiles thread execution and assigns an enumerated classification ID. -+ This classification is communicated to the OS via logical processor scope MSR. -+3. During the thread context switch out the operating system consumes the workload(WL) -+ classification which resides in a logical processor scope MSR. -+4. The OS triggers the hardware to clear its history by writing to an MSR, -+ after consuming the WL classification and before switching in the new thread. -+5. If due to the classification, ranking table, and processor availability, -+ the thread is not on its ideal processor, the OS will then consider scheduling -+ the thread on its ideal processor (if available). -+ -+Ranking Table -+------------- -+The ranking table is a shared memory region that is used to communicate the -+performance and energy efficiency capabilities of each CPU in the system. -+ -+The ranking table design includes rankings for each APIC ID in the system and -+rankings both for performance and efficiency for each workload classification. -+ -+.. kernel-doc:: drivers/platform/x86/amd/hfi/hfi.c -+ :doc: amd_shmem_info -+ -+Ranking Table update -+--------------------------- -+The power management firmware issues an platform interrupt after updating the ranking -+table and is ready for the operating system to consume it. CPUs receive such interrupt -+and read new ranking table from shared memory which PCCT table has provided, then -+``amd_hfi`` driver parse the new table to provide new consume data for scheduling decisions. -+ -+ -diff --git a/Documentation/arch/x86/index.rst b/Documentation/arch/x86/index.rst -index 8ac64d7de4dc..56f2923f5259 100644 ---- a/Documentation/arch/x86/index.rst -+++ b/Documentation/arch/x86/index.rst -@@ -43,3 +43,4 @@ x86-specific Documentation - features - elf_auxvec - xstate -+ amd-hfi -diff --git a/MAINTAINERS b/MAINTAINERS -index 2ba00c0cd701..c27b4e8f2129 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -1060,6 +1060,15 @@ F: arch/x86/include/asm/amd_hsmp.h - F: arch/x86/include/uapi/asm/amd_hsmp.h - F: drivers/platform/x86/amd/hsmp.c - -+AMD HETERO CORE HARDWARE FEEDBACK DRIVER -+M: Mario Limonciello -+R: Perry Yuan -+L: platform-driver-x86@vger.kernel.org -+S: Supported -+B: https://gitlab.freedesktop.org/drm/amd/-/issues -+F: Documentation/arch/x86/amd-hfi.rst -+F: drivers/platform/x86/amd/hfi/ -+ - AMD IOMMU (AMD-VI) - M: Joerg Roedel - R: Suravee Suthikulpanit -diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h -index aa30fd8cad7f..ca1f5141824d 100644 ---- a/arch/x86/include/asm/cpu.h -+++ b/arch/x86/include/asm/cpu.h -@@ -32,6 +32,8 @@ extern bool handle_user_split_lock(struct pt_regs *regs, long error_code); - extern bool handle_guest_split_lock(unsigned long ip); - extern void handle_bus_lock(struct pt_regs *regs); - u8 get_this_hybrid_cpu_type(void); -+u32 intel_native_model_id(struct cpuinfo_x86 *c); -+enum x86_topology_cpu_type intel_cpu_type(struct cpuinfo_x86 *c); - #else - static inline void __init sld_setup(struct cpuinfo_x86 *c) {} - static inline bool handle_user_split_lock(struct pt_regs *regs, long error_code) -@@ -50,6 +52,23 @@ static inline u8 get_this_hybrid_cpu_type(void) - { - return 0; - } -+ -+static u32 intel_native_model_id(struct cpuinfo_x86 *c) -+{ -+ return 0; -+} -+static enum x86_topology_cpu_type intel_cpu_type(struct cpuinfo_x86 *c) -+{ -+ return TOPO_CPU_TYPE_UNKNOWN; -+} -+#endif -+#ifdef CONFIG_CPU_SUP_AMD -+enum x86_topology_cpu_type amd_cpu_type(struct cpuinfo_x86 *c); -+#else -+static inline enum x86_topology_cpu_type amd_cpu_type(struct cpuinfo_x86 *c) -+{ -+ return TOPO_CPU_TYPE_UNKNOWN; -+} - #endif - #ifdef CONFIG_IA32_FEAT_CTL - void init_ia32_feat_ctl(struct cpuinfo_x86 *c); -diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h -index 913fd3a7bac6..c18dcf608526 100644 ---- a/arch/x86/include/asm/cpufeatures.h -+++ b/arch/x86/include/asm/cpufeatures.h -@@ -473,7 +473,9 @@ - #define X86_FEATURE_BHI_CTRL (21*32+ 2) /* BHI_DIS_S HW control available */ - #define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* BHI_DIS_S HW control enabled */ - #define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* Clear branch history at vmexit using SW loop */ --#define X86_FEATURE_FAST_CPPC (21*32 + 5) /* AMD Fast CPPC */ -+#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */ -+#define X86_FEATURE_AMD_HETEROGENEOUS_CORES (21*32 + 6) /* Heterogeneous Core Topology */ -+#define X86_FEATURE_AMD_WORKLOAD_CLASS (21*32 + 7) /* Workload Classification */ - - /* - * BUG word(s) -diff --git a/arch/x86/include/asm/hreset.h b/arch/x86/include/asm/hreset.h -new file mode 100644 -index 000000000000..ae1f72602bbd ---- /dev/null -+++ b/arch/x86/include/asm/hreset.h -@@ -0,0 +1,6 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef _ASM_X86_HRESET_H -+ -+void reset_hardware_history_hetero(void); -+ -+#endif /* _ASM_X86_HRESET_H */ -diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h -index 82c6a4d350e0..a70c1475725a 100644 ---- a/arch/x86/include/asm/msr-index.h -+++ b/arch/x86/include/asm/msr-index.h -@@ -690,6 +690,11 @@ - #define MSR_AMD64_PERF_CNTR_GLOBAL_CTL 0xc0000301 - #define MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR 0xc0000302 - -+/* AMD Hardware Feedback Support MSRs */ -+#define AMD_WORKLOAD_CLASS_CONFIG 0xc0000500 -+#define AMD_WORKLOAD_CLASS_ID 0xc0000501 -+#define AMD_WORKLOAD_HRST 0xc0000502 -+ - /* AMD Last Branch Record MSRs */ - #define MSR_AMD64_LBR_SELECT 0xc000010e - -diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h -index 775acbdea1a9..9a28b11d0327 100644 ---- a/arch/x86/include/asm/processor.h -+++ b/arch/x86/include/asm/processor.h -@@ -105,6 +105,24 @@ struct cpuinfo_topology { - // Cache level topology IDs - u32 llc_id; - u32 l2c_id; -+ -+ // Hardware defined CPU-type -+ union { -+ u32 cpu_type; -+ struct { -+ // CPUID.1A.EAX[23-0] -+ u32 intel_native_model_id:24; -+ // CPUID.1A.EAX[31-24] -+ u32 intel_type:8; -+ }; -+ struct { -+ // CPUID 0x80000026.EBX -+ u32 amd_num_processors :16, -+ amd_power_efficiency_ranking :8, -+ amd_native_model_id :4, -+ amd_type :4; -+ }; -+ }; - }; - - struct cpuinfo_x86 { -diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h -index abe3a8f22cbd..70ec19877f6e 100644 ---- a/arch/x86/include/asm/topology.h -+++ b/arch/x86/include/asm/topology.h -@@ -114,6 +114,12 @@ enum x86_topology_domains { - TOPO_MAX_DOMAIN, - }; - -+enum x86_topology_cpu_type { -+ TOPO_CPU_TYPE_PERFORMANCE, -+ TOPO_CPU_TYPE_EFFICIENCY, -+ TOPO_CPU_TYPE_UNKNOWN, -+}; -+ - struct x86_topology_system { - unsigned int dom_shifts[TOPO_MAX_DOMAIN]; - unsigned int dom_size[TOPO_MAX_DOMAIN]; -@@ -149,6 +155,8 @@ extern unsigned int __max_threads_per_core; - extern unsigned int __num_threads_per_package; - extern unsigned int __num_cores_per_package; - -+enum x86_topology_cpu_type topology_cpu_type(struct cpuinfo_x86 *c); -+ - static inline unsigned int topology_max_packages(void) - { - return __max_logical_packages; -diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c -index 956984054bf3..4fd007eac0c7 100644 ---- a/arch/x86/kernel/acpi/cppc.c -+++ b/arch/x86/kernel/acpi/cppc.c -@@ -234,8 +234,10 @@ EXPORT_SYMBOL_GPL(amd_detect_prefcore); - */ - int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) - { -+ enum x86_topology_cpu_type core_type = topology_cpu_type(&cpu_data(cpu)); - bool prefcore; - int ret; -+ u32 tmp; - - ret = amd_detect_prefcore(&prefcore); - if (ret) -@@ -261,6 +263,27 @@ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) - break; - } - } -+ -+ /* detect if running on heterogeneous design */ -+ switch (core_type) { -+ case TOPO_CPU_TYPE_UNKNOWN: -+ break; -+ case TOPO_CPU_TYPE_PERFORMANCE: -+ /* use the max scale for performance cores */ -+ *numerator = CPPC_HIGHEST_PERF_PERFORMANCE; -+ return 0; -+ case TOPO_CPU_TYPE_EFFICIENCY: -+ /* use the highest perf value for efficiency cores */ -+ ret = amd_get_highest_perf(cpu, &tmp); -+ if (ret) -+ return ret; -+ *numerator = tmp; -+ return 0; -+ default: -+ pr_warn("WARNING: Undefined core type %d found\n", core_type); -+ break; -+ } -+ - *numerator = CPPC_HIGHEST_PERF_PREFCORE; - - return 0; -diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c -index fab5caec0b72..779073e5a646 100644 ---- a/arch/x86/kernel/cpu/amd.c -+++ b/arch/x86/kernel/cpu/amd.c -@@ -29,6 +29,9 @@ - - #include "cpu.h" - -+#define TOPO_HW_CPU_TYPE_AMD_PERFORMANCE 0 -+#define TOPO_HW_CPU_TYPE_AMD_EFFICIENCY 1 -+ - static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) - { - u32 gprs[8] = { 0 }; -@@ -1205,3 +1208,14 @@ void amd_check_microcode(void) - if (cpu_feature_enabled(X86_FEATURE_ZEN2)) - on_each_cpu(zenbleed_check_cpu, NULL, 1); - } -+ -+enum x86_topology_cpu_type amd_cpu_type(struct cpuinfo_x86 *c) -+{ -+ switch (c->topo.amd_type) { -+ case TOPO_HW_CPU_TYPE_AMD_PERFORMANCE: -+ return TOPO_CPU_TYPE_PERFORMANCE; -+ case TOPO_HW_CPU_TYPE_AMD_EFFICIENCY: -+ return TOPO_CPU_TYPE_EFFICIENCY; -+ } -+ return TOPO_CPU_TYPE_UNKNOWN; -+} -diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c -index ab0e2da7c9ef..e73e0e3beee9 100644 ---- a/arch/x86/kernel/cpu/common.c -+++ b/arch/x86/kernel/cpu/common.c -@@ -57,6 +57,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -403,6 +404,7 @@ static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_C - X86_CR4_FSGSBASE | X86_CR4_CET | X86_CR4_FRED; - static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning); - static unsigned long cr4_pinned_bits __ro_after_init; -+static DEFINE_STATIC_KEY_FALSE_RO(hardware_history_features); - - void native_write_cr0(unsigned long val) - { -@@ -481,6 +483,12 @@ void cr4_init(void) - this_cpu_write(cpu_tlbstate.cr4, cr4); - } - -+static void __init setup_hreset(struct cpuinfo_x86 *c) -+{ -+ if (cpu_feature_enabled(X86_FEATURE_AMD_WORKLOAD_CLASS)) -+ static_key_enable_cpuslocked(&hardware_history_features.key); -+} -+ - /* - * Once CPU feature detection is finished (and boot params have been - * parsed), record any of the sensitive CR bits that are set, and -@@ -1842,6 +1850,7 @@ static void identify_cpu(struct cpuinfo_x86 *c) - setup_smep(c); - setup_smap(c); - setup_umip(c); -+ setup_hreset(c); - - /* Enable FSGSBASE instructions if available. */ - if (cpu_has(c, X86_FEATURE_FSGSBASE)) { -@@ -2395,3 +2404,9 @@ void __init arch_cpu_finalize_init(void) - */ - mem_encrypt_init(); - } -+ -+__always_inline void reset_hardware_history_hetero(void) -+{ -+ if (static_branch_unlikely(&hardware_history_features)) -+ wrmsrl(AMD_WORKLOAD_HRST, 0x1); -+} -diff --git a/arch/x86/kernel/cpu/debugfs.c b/arch/x86/kernel/cpu/debugfs.c -index 3baf3e435834..c3361e496df9 100644 ---- a/arch/x86/kernel/cpu/debugfs.c -+++ b/arch/x86/kernel/cpu/debugfs.c -@@ -22,6 +22,7 @@ static int cpu_debug_show(struct seq_file *m, void *p) - seq_printf(m, "die_id: %u\n", c->topo.die_id); - seq_printf(m, "cu_id: %u\n", c->topo.cu_id); - seq_printf(m, "core_id: %u\n", c->topo.core_id); -+ seq_printf(m, "cpu_type: %u\n", topology_cpu_type(c)); - seq_printf(m, "logical_pkg_id: %u\n", c->topo.logical_pkg_id); - seq_printf(m, "logical_die_id: %u\n", c->topo.logical_die_id); - seq_printf(m, "llc_id: %u\n", c->topo.llc_id); -diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c -index 08b95a35b5cb..33ee44829603 100644 ---- a/arch/x86/kernel/cpu/intel.c -+++ b/arch/x86/kernel/cpu/intel.c -@@ -1283,6 +1283,8 @@ void __init sld_setup(struct cpuinfo_x86 *c) - } - - #define X86_HYBRID_CPU_TYPE_ID_SHIFT 24 -+#define TOPO_HW_CPU_TYPE_INTEL_ATOM 0x20 -+#define TOPO_HW_CPU_TYPE_INTEL_CORE 0x40 - - /** - * get_this_hybrid_cpu_type() - Get the type of this hybrid CPU -@@ -1297,3 +1299,19 @@ u8 get_this_hybrid_cpu_type(void) - - return cpuid_eax(0x0000001a) >> X86_HYBRID_CPU_TYPE_ID_SHIFT; - } -+ -+u32 intel_native_model_id(struct cpuinfo_x86 *c) -+{ -+ return c->topo.intel_native_model_id; -+} -+ -+enum x86_topology_cpu_type intel_cpu_type(struct cpuinfo_x86 *c) -+{ -+ switch (c->topo.intel_type) { -+ case TOPO_HW_CPU_TYPE_INTEL_ATOM: -+ return TOPO_CPU_TYPE_EFFICIENCY; -+ case TOPO_HW_CPU_TYPE_INTEL_CORE: -+ return TOPO_CPU_TYPE_PERFORMANCE; -+ } -+ return TOPO_CPU_TYPE_UNKNOWN; -+} -diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c -index c84c30188fdf..1e5433259444 100644 ---- a/arch/x86/kernel/cpu/scattered.c -+++ b/arch/x86/kernel/cpu/scattered.c -@@ -45,13 +45,15 @@ static const struct cpuid_bit cpuid_bits[] = { - { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, - { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, - { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, -- { X86_FEATURE_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, -+ { X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, - { X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 }, - { X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 }, - { X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 }, -+ { X86_FEATURE_AMD_WORKLOAD_CLASS, CPUID_EAX, 22, 0x80000021, 0 }, - { X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 }, - { X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 }, - { X86_FEATURE_AMD_LBR_PMC_FREEZE, CPUID_EAX, 2, 0x80000022, 0 }, -+ { X86_FEATURE_AMD_HETEROGENEOUS_CORES, CPUID_EAX, 30, 0x80000026, 0 }, - { 0, 0, 0, 0, 0 } - }; - -diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c -index 7d476fa697ca..03b3c9c3a45e 100644 ---- a/arch/x86/kernel/cpu/topology_amd.c -+++ b/arch/x86/kernel/cpu/topology_amd.c -@@ -182,6 +182,9 @@ static void parse_topology_amd(struct topo_scan *tscan) - if (cpu_feature_enabled(X86_FEATURE_TOPOEXT)) - has_topoext = cpu_parse_topology_ext(tscan); - -+ if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) -+ tscan->c->topo.cpu_type = cpuid_ebx(0x80000026); -+ - if (!has_topoext && !parse_8000_0008(tscan)) - return; - -diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/topology_common.c -index 9a6069e7133c..04b012dffa47 100644 ---- a/arch/x86/kernel/cpu/topology_common.c -+++ b/arch/x86/kernel/cpu/topology_common.c -@@ -27,6 +27,16 @@ void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains dom, - } - } - -+enum x86_topology_cpu_type topology_cpu_type(struct cpuinfo_x86 *c) -+{ -+ if (c->x86_vendor == X86_VENDOR_INTEL) -+ return intel_cpu_type(c); -+ if (c->x86_vendor == X86_VENDOR_AMD) -+ return amd_cpu_type(c); -+ -+ return TOPO_CPU_TYPE_UNKNOWN; -+} -+ - static unsigned int __maybe_unused parse_num_cores_legacy(struct cpuinfo_x86 *c) - { - struct { -@@ -87,6 +97,7 @@ static void parse_topology(struct topo_scan *tscan, bool early) - .cu_id = 0xff, - .llc_id = BAD_APICID, - .l2c_id = BAD_APICID, -+ .cpu_type = TOPO_CPU_TYPE_UNKNOWN, - }; - struct cpuinfo_x86 *c = tscan->c; - struct { -@@ -132,6 +143,8 @@ static void parse_topology(struct topo_scan *tscan, bool early) - case X86_VENDOR_INTEL: - if (!IS_ENABLED(CONFIG_CPU_SUP_INTEL) || !cpu_parse_topology_ext(tscan)) - parse_legacy(tscan); -+ if (c->cpuid_level >= 0x1a) -+ c->topo.cpu_type = cpuid_eax(0x1a); - break; - case X86_VENDOR_HYGON: - if (IS_ENABLED(CONFIG_CPU_SUP_HYGON)) -diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c -index 0917c7f25720..6a3a1339f7a7 100644 ---- a/arch/x86/kernel/process_32.c -+++ b/arch/x86/kernel/process_32.c -@@ -52,6 +52,7 @@ - #include - #include - #include -+#include - #include - - #include "process.h" -@@ -213,6 +214,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) - /* Load the Intel cache allocation PQR MSR. */ - resctrl_sched_in(next_p); - -+ reset_hardware_history_hetero(); -+ - return prev_p; - } - -diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c -index d8d582b750d4..53e3756384d6 100644 ---- a/arch/x86/kernel/process_64.c -+++ b/arch/x86/kernel/process_64.c -@@ -54,6 +54,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -709,6 +710,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) - /* Load the Intel cache allocation PQR MSR. */ - resctrl_sched_in(next_p); - -+ reset_hardware_history_hetero(); -+ - return prev_p; - } - -diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c -index 390e4fe7433e..9ee84f58f3b4 100644 ---- a/arch/x86/kernel/smpboot.c -+++ b/arch/x86/kernel/smpboot.c -@@ -497,8 +497,9 @@ static int x86_cluster_flags(void) - - static int x86_die_flags(void) - { -- if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) -- return x86_sched_itmt_flags(); -+ if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU) || -+ cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) -+ return x86_sched_itmt_flags(); - - return 0; - } -diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c -index 41965c49ec96..b8709ccb1f26 100644 ---- a/drivers/cpufreq/amd-pstate.c -+++ b/drivers/cpufreq/amd-pstate.c -@@ -781,6 +781,12 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata) - /* user disabled or not detected */ - if (!amd_pstate_prefcore) - return; -+ /* should use amd-hfi instead */ -+ if (boot_cpu_has(X86_FEATURE_AMD_WORKLOAD_CLASS) && -+ IS_ENABLED(CONFIG_AMD_HFI)) { -+ amd_pstate_prefcore = false; -+ return; -+ } - - cpudata->hw_prefcore = true; - -@@ -838,7 +844,7 @@ static u32 amd_pstate_get_transition_delay_us(unsigned int cpu) - - transition_delay_ns = cppc_get_transition_latency(cpu); - if (transition_delay_ns == CPUFREQ_ETERNAL) { -- if (cpu_feature_enabled(X86_FEATURE_FAST_CPPC)) -+ if (cpu_feature_enabled(X86_FEATURE_AMD_FAST_CPPC)) - return AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY; - else - return AMD_PSTATE_TRANSITION_DELAY; -diff --git a/drivers/platform/x86/amd/Kconfig b/drivers/platform/x86/amd/Kconfig -index d73f691020d0..0e5eb064116d 100644 ---- a/drivers/platform/x86/amd/Kconfig -+++ b/drivers/platform/x86/amd/Kconfig -@@ -5,6 +5,7 @@ - - source "drivers/platform/x86/amd/pmf/Kconfig" - source "drivers/platform/x86/amd/pmc/Kconfig" -+source "drivers/platform/x86/amd/hfi/Kconfig" - - config AMD_3D_VCACHE - tristate "AMD 3D V-Cache Performance Optimizer Driver" -diff --git a/drivers/platform/x86/amd/Makefile b/drivers/platform/x86/amd/Makefile -index 16e4cce02242..4a6ddcda8325 100644 ---- a/drivers/platform/x86/amd/Makefile -+++ b/drivers/platform/x86/amd/Makefile -@@ -11,3 +11,4 @@ amd_hsmp-y := hsmp.o - obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o - obj-$(CONFIG_AMD_PMF) += pmf/ - obj-$(CONFIG_AMD_WBRF) += wbrf.o -+obj-$(CONFIG_AMD_HFI) += hfi/ -diff --git a/drivers/platform/x86/amd/hfi/Kconfig b/drivers/platform/x86/amd/hfi/Kconfig -new file mode 100644 -index 000000000000..4dfa7641b35b ---- /dev/null -+++ b/drivers/platform/x86/amd/hfi/Kconfig -@@ -0,0 +1,21 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+# -+# AMD Hardware Feedback Interface Driver -+# -+ -+config AMD_HFI -+ bool "AMD Hetero Core Hardware Feedback Driver" -+ depends on ACPI -+ depends on CPU_SUP_AMD -+ depends on SCHED_MC_PRIO -+ help -+ Select this option to enable the AMD Heterogeneous Core Hardware Feedback Interface. If -+ selected, hardware provides runtime thread classification guidance to the operating system -+ on the performance and energy efficiency capabilities of each heterogeneous CPU core. -+ These capabilities may vary due to the inherent differences in the core types and can -+ also change as a result of variations in the operating conditions of the system such -+ as power and thermal limits. If selected, the kernel relays updates in heterogeneous -+ CPUs' capabilities to userspace, allowing for more optimal task scheduling and -+ resource allocation, leveraging the diverse set of cores available. -+ -+ -diff --git a/drivers/platform/x86/amd/hfi/Makefile b/drivers/platform/x86/amd/hfi/Makefile -new file mode 100644 -index 000000000000..672c6ac106e9 ---- /dev/null -+++ b/drivers/platform/x86/amd/hfi/Makefile -@@ -0,0 +1,7 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# AMD Hardware Feedback Interface Driver -+# -+ -+obj-$(CONFIG_AMD_HFI) += amd_hfi.o -+amd_hfi-objs := hfi.o -diff --git a/drivers/platform/x86/amd/hfi/hfi.c b/drivers/platform/x86/amd/hfi/hfi.c -new file mode 100644 -index 000000000000..839007684b04 ---- /dev/null -+++ b/drivers/platform/x86/amd/hfi/hfi.c -@@ -0,0 +1,547 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * AMD Hardware Feedback Interface Driver -+ * -+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All Rights Reserved. -+ * -+ * Authors: Perry Yuan -+ * Mario Limonciello -+ */ -+ -+#define pr_fmt(fmt) "amd-hfi: " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#define AMD_HFI_DRIVER "amd_hfi" -+#define AMD_HFI_MAILBOX_COUNT 1 -+#define AMD_HETERO_RANKING_TABLE_VER 2 -+ -+#define AMD_HETERO_CPUID_27 0x80000027 -+ -+static struct platform_device *device; -+ -+/** -+ * struct amd_shmem_info - Shared memory table for AMD HFI -+ * -+ * @header: The PCCT table header including signature, length flags and command. -+ * @version_number: Version number of the table -+ * @n_logical_processors: Number of logical processors -+ * @n_capabilities: Number of ranking dimensions (performance, efficiency, etc) -+ * @table_update_context: Command being sent over the subspace -+ * @n_bitmaps: Number of 32-bit bitmaps to enumerate all the APIC IDs -+ * This is based on the maximum APIC ID enumerated in the system -+ * @reserved: 24 bit spare -+ * @table_data: Bit Map(s) of enabled logical processors -+ * Followed by the ranking data for each logical processor -+ */ -+struct amd_shmem_info { -+ struct acpi_pcct_ext_pcc_shared_memory header; -+ u32 version_number :8, -+ n_logical_processors :8, -+ n_capabilities :8, -+ table_update_context :8; -+ u32 n_bitmaps :8, -+ reserved :24; -+ u32 table_data[]; -+} __packed; -+ -+struct amd_hfi_data { -+ const char *name; -+ struct device *dev; -+ struct mutex lock; -+ -+ /* PCCT table related*/ -+ struct pcc_mbox_chan *pcc_chan; -+ void __iomem *pcc_comm_addr; -+ struct acpi_subtable_header *pcct_entry; -+ struct amd_shmem_info *shmem; -+ -+ struct dentry *dbgfs_dir; -+}; -+ -+/** -+ * struct amd_hfi_classes - HFI class capabilities per CPU -+ * @perf: Performance capability -+ * @eff: Power efficiency capability -+ * -+ * Capabilities of a logical processor in the ranking table. These capabilities -+ * are unitless and specific to each HFI class. -+ */ -+struct amd_hfi_classes { -+ u32 perf; -+ u32 eff; -+}; -+ -+/** -+ * struct amd_hfi_cpuinfo - HFI workload class info per CPU -+ * @cpu: cpu index -+ * @apic_id: apic id of the current cpu -+ * @cpus: mask of cpus associated with amd_hfi_cpuinfo -+ * @class_index: workload class ID index -+ * @nr_class: max number of workload class supported -+ * @ipcc_scores: ipcc scores for each class -+ * @amd_hfi_classes: current cpu workload class ranking data -+ * -+ * Parameters of a logical processor linked with hardware feedback class -+ */ -+struct amd_hfi_cpuinfo { -+ int cpu; -+ u32 apic_id; -+ cpumask_var_t cpus; -+ s16 class_index; -+ u8 nr_class; -+ int *ipcc_scores; -+ struct amd_hfi_classes *amd_hfi_classes; -+}; -+ -+static DEFINE_PER_CPU(struct amd_hfi_cpuinfo, amd_hfi_cpuinfo) = {.class_index = -1}; -+ -+static DEFINE_MUTEX(hfi_cpuinfo_lock); -+ -+static void amd_hfi_sched_itmt_work(struct work_struct *work) -+{ -+ sched_set_itmt_support(); -+} -+static DECLARE_WORK(sched_amd_hfi_itmt_work, amd_hfi_sched_itmt_work); -+ -+static int find_cpu_index_by_apicid(unsigned int target_apicid) -+{ -+ int cpu_index; -+ -+ for_each_present_cpu(cpu_index) { -+ struct cpuinfo_x86 *info = &cpu_data(cpu_index); -+ -+ if (info->topo.apicid == target_apicid) { -+ pr_debug("match APIC id %d for CPU index: %d\n", -+ info->topo.apicid, cpu_index); -+ return cpu_index; -+ } -+ } -+ -+ return -ENODEV; -+} -+ -+static int amd_hfi_fill_metadata(struct amd_hfi_data *amd_hfi_data) -+{ -+ struct acpi_pcct_ext_pcc_slave *pcct_ext = -+ (struct acpi_pcct_ext_pcc_slave *)amd_hfi_data->pcct_entry; -+ void __iomem *pcc_comm_addr; -+ -+ pcc_comm_addr = acpi_os_ioremap(amd_hfi_data->pcc_chan->shmem_base_addr, -+ amd_hfi_data->pcc_chan->shmem_size); -+ if (!pcc_comm_addr) { -+ pr_err("failed to ioremap PCC common region mem\n"); -+ return -ENOMEM; -+ } -+ -+ memcpy_fromio(amd_hfi_data->shmem, pcc_comm_addr, pcct_ext->length); -+ iounmap(pcc_comm_addr); -+ -+ if (amd_hfi_data->shmem->header.signature != PCC_SIGNATURE) { -+ pr_err("invalid signature in shared memory\n"); -+ return -EINVAL; -+ } -+ if (amd_hfi_data->shmem->version_number != AMD_HETERO_RANKING_TABLE_VER) { -+ pr_err("invalid version %d\n", amd_hfi_data->shmem->version_number); -+ return -EINVAL; -+ } -+ -+ for (unsigned int i = 0; i < amd_hfi_data->shmem->n_bitmaps; i++) { -+ u32 bitmap = amd_hfi_data->shmem->table_data[i]; -+ -+ for (unsigned int j = 0; j < BITS_PER_TYPE(u32); j++) { -+ struct amd_hfi_cpuinfo *info; -+ int apic_id = i * BITS_PER_TYPE(u32) + j; -+ int cpu_index; -+ -+ if (!(bitmap & BIT(j))) -+ continue; -+ -+ cpu_index = find_cpu_index_by_apicid(apic_id); -+ if (cpu_index < 0) { -+ pr_warn("APIC ID %d not found\n", apic_id); -+ continue; -+ } -+ -+ info = per_cpu_ptr(&amd_hfi_cpuinfo, cpu_index); -+ info->apic_id = apic_id; -+ -+ /* Fill the ranking data for each logical processor */ -+ info = per_cpu_ptr(&amd_hfi_cpuinfo, cpu_index); -+ for (unsigned int k = 0; k < info->nr_class; k++) { -+ u32 *table = amd_hfi_data->shmem->table_data + -+ amd_hfi_data->shmem->n_bitmaps + -+ i * info->nr_class; -+ -+ info->amd_hfi_classes[k].eff = table[apic_id + 2 * k]; -+ info->amd_hfi_classes[k].perf = table[apic_id + 2 * k + 1]; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int amd_hfi_alloc_class_data(struct platform_device *pdev) -+{ -+ struct amd_hfi_cpuinfo *hfi_cpuinfo; -+ struct device *dev = &pdev->dev; -+ int idx; -+ int nr_class_id; -+ -+ nr_class_id = cpuid_eax(AMD_HETERO_CPUID_27); -+ if (nr_class_id < 0 || nr_class_id > 255) { -+ dev_err(dev, "failed to get number of supported classes: %d\n", -+ nr_class_id); -+ return -EINVAL; -+ } -+ -+ for_each_present_cpu(idx) { -+ struct amd_hfi_classes *classes; -+ int *ipcc_scores; -+ -+ classes = devm_kzalloc(dev, -+ nr_class_id * sizeof(struct amd_hfi_classes), -+ GFP_KERNEL); -+ if (!classes) -+ return -ENOMEM; -+ ipcc_scores = devm_kcalloc(dev, nr_class_id, sizeof(int), GFP_KERNEL); -+ if (!ipcc_scores) -+ return -ENOMEM; -+ hfi_cpuinfo = per_cpu_ptr(&amd_hfi_cpuinfo, idx); -+ hfi_cpuinfo->amd_hfi_classes = classes; -+ hfi_cpuinfo->ipcc_scores = ipcc_scores; -+ hfi_cpuinfo->nr_class = nr_class_id; -+ } -+ -+ return 0; -+} -+ -+static void amd_hfi_remove(struct platform_device *pdev) -+{ -+ struct amd_hfi_data *dev = platform_get_drvdata(pdev); -+ -+ debugfs_remove_recursive(dev->dbgfs_dir); -+ -+ mutex_destroy(&dev->lock); -+} -+ -+static int amd_set_hfi_ipcc_score(struct amd_hfi_cpuinfo *hfi_cpuinfo, int cpu) -+{ -+ for (int i = 0; i < hfi_cpuinfo->nr_class; i++) -+ WRITE_ONCE(hfi_cpuinfo->ipcc_scores[i], -+ hfi_cpuinfo->amd_hfi_classes[i].perf); -+ -+ sched_set_itmt_core_prio(hfi_cpuinfo->ipcc_scores[0], cpu); -+ -+ return 0; -+} -+ -+static int amd_hfi_set_state(unsigned int cpu, bool state) -+{ -+ int ret; -+ -+ ret = wrmsrl_on_cpu(cpu, AMD_WORKLOAD_CLASS_CONFIG, state); -+ if (ret) -+ return ret; -+ -+ return wrmsrl_on_cpu(cpu, AMD_WORKLOAD_HRST, 0x1); -+} -+ -+/** -+ * amd_hfi_online() - Enable workload classification on @cpu -+ * @cpu: CPU in which the workload classification will be enabled -+ * -+ * Return: 0 on success, negative error code on failure -+ */ -+static int amd_hfi_online(unsigned int cpu) -+{ -+ struct amd_hfi_cpuinfo *hfi_info = per_cpu_ptr(&amd_hfi_cpuinfo, cpu); -+ struct amd_hfi_classes *hfi_classes; -+ int ret; -+ -+ if (WARN_ON_ONCE(!hfi_info)) -+ return -EINVAL; -+ -+ /* -+ * Check if @cpu as an associated, initialized and ranking data must be filled -+ */ -+ hfi_classes = hfi_info->amd_hfi_classes; -+ if (!hfi_classes) -+ return -EINVAL; -+ -+ guard(mutex)(&hfi_cpuinfo_lock); -+ -+ if (!zalloc_cpumask_var(&hfi_info->cpus, GFP_KERNEL)) -+ return -ENOMEM; -+ -+ cpumask_set_cpu(cpu, hfi_info->cpus); -+ -+ ret = amd_hfi_set_state(cpu, true); -+ if (ret) -+ pr_err("WCT enable failed for CPU %d\n", cpu); -+ -+ return ret; -+} -+ -+/** -+ * amd_hfi_offline() - Disable workload classification on @cpu -+ * @cpu: CPU in which the workload classification will be disabled -+ * -+ * Remove @cpu from those covered by its HFI instance. -+ * -+ * Return: 0 on success, negative error code on failure -+ */ -+static int amd_hfi_offline(unsigned int cpu) -+{ -+ struct amd_hfi_cpuinfo *hfi_info = &per_cpu(amd_hfi_cpuinfo, cpu); -+ int ret; -+ -+ if (WARN_ON_ONCE(!hfi_info)) -+ return -EINVAL; -+ -+ guard(mutex)(&hfi_cpuinfo_lock); -+ -+ ret = amd_hfi_set_state(cpu, false); -+ if (ret) -+ pr_err("WCT disable failed for CPU %d\n", cpu); -+ -+ free_cpumask_var(hfi_info->cpus); -+ -+ return ret; -+} -+ -+static int update_hfi_ipcc_scores(void) -+{ -+ int cpu; -+ int ret; -+ -+ for_each_present_cpu(cpu) { -+ struct amd_hfi_cpuinfo *hfi_cpuinfo = per_cpu_ptr(&amd_hfi_cpuinfo, cpu); -+ -+ ret = amd_set_hfi_ipcc_score(hfi_cpuinfo, cpu); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int amd_hfi_metadata_parser(struct platform_device *pdev, -+ struct amd_hfi_data *amd_hfi_data) -+{ -+ struct acpi_pcct_ext_pcc_slave *pcct_ext; -+ struct acpi_subtable_header *pcct_entry; -+ struct mbox_chan *pcc_mbox_channels; -+ struct acpi_table_header *pcct_tbl; -+ struct pcc_mbox_chan *pcc_chan; -+ acpi_status status; -+ int ret; -+ -+ pcc_mbox_channels = devm_kcalloc(&pdev->dev, AMD_HFI_MAILBOX_COUNT, -+ sizeof(*pcc_mbox_channels), GFP_KERNEL); -+ if (!pcc_mbox_channels) -+ return -ENOMEM; -+ -+ pcc_chan = devm_kcalloc(&pdev->dev, AMD_HFI_MAILBOX_COUNT, -+ sizeof(*pcc_chan), GFP_KERNEL); -+ if (!pcc_chan) -+ return -ENOMEM; -+ -+ status = acpi_get_table(ACPI_SIG_PCCT, 0, &pcct_tbl); -+ if (ACPI_FAILURE(status) || !pcct_tbl) -+ return -ENODEV; -+ -+ /* get pointer to the first PCC subspace entry */ -+ pcct_entry = (struct acpi_subtable_header *) ( -+ (unsigned long)pcct_tbl + sizeof(struct acpi_table_pcct)); -+ -+ pcc_chan->mchan = &pcc_mbox_channels[0]; -+ -+ amd_hfi_data->pcc_chan = pcc_chan; -+ amd_hfi_data->pcct_entry = pcct_entry; -+ pcct_ext = (struct acpi_pcct_ext_pcc_slave *)pcct_entry; -+ -+ if (pcct_ext->length <= 0) -+ return -EINVAL; -+ -+ amd_hfi_data->shmem = devm_kzalloc(amd_hfi_data->dev, pcct_ext->length, GFP_KERNEL); -+ if (!amd_hfi_data->shmem) -+ return -ENOMEM; -+ -+ pcc_chan->shmem_base_addr = pcct_ext->base_address; -+ pcc_chan->shmem_size = pcct_ext->length; -+ -+ /* parse the shared memory info from the pcct table */ -+ ret = amd_hfi_fill_metadata(amd_hfi_data); -+ -+ acpi_put_table(pcct_tbl); -+ -+ return ret; -+} -+ -+static int class_capabilities_show(struct seq_file *s, void *unused) -+{ -+ int cpu, idx; -+ -+ seq_puts(s, "CPU #\tWLC\tPerf\tEff\n"); -+ for_each_present_cpu(cpu) { -+ struct amd_hfi_cpuinfo *hfi_cpuinfo = per_cpu_ptr(&amd_hfi_cpuinfo, cpu); -+ -+ seq_printf(s, "%d", cpu); -+ for (idx = 0; idx < hfi_cpuinfo->nr_class; idx++) { -+ seq_printf(s, "\t%d\t%d\t%d\n", -+ idx, -+ hfi_cpuinfo->amd_hfi_classes[idx].perf, -+ hfi_cpuinfo->amd_hfi_classes[idx].eff); -+ } -+ } -+ -+ return 0; -+} -+DEFINE_SHOW_ATTRIBUTE(class_capabilities); -+ -+static int amd_hfi_pm_resume(struct device *dev) -+{ -+ int ret, cpu; -+ -+ for_each_online_cpu(cpu) { -+ ret = amd_hfi_set_state(cpu, true); -+ if (ret < 0) { -+ dev_err(dev, "failed to enable workload class config: %d\n", ret); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int amd_hfi_pm_suspend(struct device *dev) -+{ -+ int ret, cpu; -+ -+ for_each_online_cpu(cpu) { -+ ret = amd_hfi_set_state(cpu, false); -+ if (ret < 0) { -+ dev_err(dev, "failed to disable workload class config: %d\n", ret); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static DEFINE_SIMPLE_DEV_PM_OPS(amd_hfi_pm_ops, amd_hfi_pm_suspend, amd_hfi_pm_resume); -+ -+static const struct acpi_device_id amd_hfi_platform_match[] = { -+ { "AMDI0104", 0}, -+ { } -+}; -+MODULE_DEVICE_TABLE(acpi, amd_hfi_platform_match); -+ -+static int amd_hfi_probe(struct platform_device *pdev) -+{ -+ struct amd_hfi_data *amd_hfi_data; -+ int ret; -+ -+ if (!acpi_match_device(amd_hfi_platform_match, &pdev->dev)) -+ return -ENODEV; -+ -+ amd_hfi_data = devm_kzalloc(&pdev->dev, sizeof(*amd_hfi_data), GFP_KERNEL); -+ if (!amd_hfi_data) -+ return -ENOMEM; -+ -+ amd_hfi_data->dev = &pdev->dev; -+ mutex_init(&amd_hfi_data->lock); -+ platform_set_drvdata(pdev, amd_hfi_data); -+ -+ ret = amd_hfi_alloc_class_data(pdev); -+ if (ret) -+ return ret; -+ -+ ret = amd_hfi_metadata_parser(pdev, amd_hfi_data); -+ if (ret) -+ return ret; -+ -+ ret = update_hfi_ipcc_scores(); -+ if (ret) -+ return ret; -+ -+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/amd_hfi:online", -+ amd_hfi_online, amd_hfi_offline); -+ if (ret < 0) -+ return ret; -+ -+ schedule_work(&sched_amd_hfi_itmt_work); -+ -+ amd_hfi_data->dbgfs_dir = debugfs_create_dir("amd_hfi", arch_debugfs_dir); -+ debugfs_create_file("class_capabilities", 0644, amd_hfi_data->dbgfs_dir, pdev, -+ &class_capabilities_fops); -+ -+ return 0; -+} -+ -+static struct platform_driver amd_hfi_driver = { -+ .driver = { -+ .name = AMD_HFI_DRIVER, -+ .owner = THIS_MODULE, -+ .pm = &amd_hfi_pm_ops, -+ .acpi_match_table = ACPI_PTR(amd_hfi_platform_match), -+ }, -+ .probe = amd_hfi_probe, -+ .remove = amd_hfi_remove, -+}; -+ -+static int __init amd_hfi_init(void) -+{ -+ int ret; -+ -+ if (acpi_disabled || -+ !boot_cpu_has(X86_FEATURE_AMD_HETEROGENEOUS_CORES) || -+ !boot_cpu_has(X86_FEATURE_AMD_WORKLOAD_CLASS)) -+ return -ENODEV; -+ -+ device = platform_device_register_simple(AMD_HFI_DRIVER, -1, NULL, 0); -+ if (IS_ERR(device)) { -+ pr_err("unable to register HFI platform device\n"); -+ return PTR_ERR(device); -+ } -+ -+ ret = platform_driver_register(&amd_hfi_driver); -+ if (ret) -+ pr_err("failed to register HFI driver\n"); -+ -+ return ret; -+} -+ -+static __exit void amd_hfi_exit(void) -+{ -+ platform_device_unregister(device); -+ platform_driver_unregister(&amd_hfi_driver); -+} -+module_init(amd_hfi_init); -+module_exit(amd_hfi_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("AMD Hardware Feedback Interface Driver"); diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index dd4682857c12..23698d0f4bb4 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h @@ -2648,12 +1616,12 @@ index dd4682857c12..23698d0f4bb4 100644 /* * BUG word(s) -- -2.47.0 +2.47.0.rc0 -From d9e873c5996dc87c29ce0ff7e954c472ccd2a369 Mon Sep 17 00:00:00 2001 +From f3e882f80066e4cfda6767e245e95ca280db8bc0 Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:52:00 +0800 -Subject: [PATCH 05/14] bbr3 +Subject: [PATCH 04/13] bbr3 Signed-off-by: Eric Naim --- @@ -6034,12 +5002,12 @@ index 4d40615dc8fc..f27941201ef2 100644 event = icsk->icsk_pending; -- -2.47.0 +2.47.0.rc0 -From e2a88c9b335a7475b66634f053b128500467c4f6 Mon Sep 17 00:00:00 2001 +From 2a2f186f1c8c99bdd1183fd28527bf95f781166c Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:52:15 +0800 -Subject: [PATCH 06/14] cachy +Subject: [PATCH 05/13] cachy Signed-off-by: Eric Naim --- @@ -13062,12 +12030,12 @@ index 663ce300dd06..f83493838cf9 100644 eval "package_$_p() { $(declare -f "_package${_p#$pkgbase}") -- -2.47.0 +2.47.0.rc0 -From 894d9efe4bf547f1fa1df4dd3662986743ec57d3 Mon Sep 17 00:00:00 2001 +From 6c98e17d041435fde0a3c49fce29a562935c8cb6 Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:52:25 +0800 -Subject: [PATCH 07/14] fixes +Subject: [PATCH 06/13] fixes Signed-off-by: Eric Naim --- @@ -14333,12 +13301,12 @@ index f76fe04fc9a4..65b965ca40ea 100644 .targetsize = sizeof(struct xt_mark_tginfo2), .me = THIS_MODULE, -- -2.47.0 +2.47.0.rc0 -From 234ada9d57a61746a48bc8db0b381589cb541880 Mon Sep 17 00:00:00 2001 +From 13dcfcc62c4c4467d7f8c9d1436097cdd70c0cec Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:52:43 +0800 -Subject: [PATCH 08/14] intel-pstate +Subject: [PATCH 07/13] intel-pstate Signed-off-by: Eric Naim --- @@ -14348,10 +13316,10 @@ Signed-off-by: Eric Naim 3 files changed, 328 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h -index 70ec19877f6e..5b344ff81219 100644 +index 94d9832a5bc8..9f9376db64e3 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h -@@ -290,9 +290,22 @@ static inline long arch_scale_freq_capacity(int cpu) +@@ -291,9 +291,22 @@ static inline long arch_scale_freq_capacity(int cpu) } #define arch_scale_freq_capacity arch_scale_freq_capacity @@ -14817,12 +13785,12 @@ index 348a330678bd..c11be253bfa3 100644 } -- -2.47.0 +2.47.0.rc0 -From 7ed94f621d6d5361b103676ac42e00ece364fc88 Mon Sep 17 00:00:00 2001 +From ac05835cead1a0a20b6297fdb0f7c47326d0ff71 Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:52:52 +0800 -Subject: [PATCH 09/14] ksm +Subject: [PATCH 08/13] ksm Signed-off-by: Eric Naim --- @@ -15250,12 +14218,12 @@ index 01071182763e..7394bad8178e 100644 +464 common process_ksm_disable sys_process_ksm_disable sys_process_ksm_disable +465 common process_ksm_status sys_process_ksm_status sys_process_ksm_status -- -2.47.0 +2.47.0.rc0 -From 1c710b0efb6a923417af140e6c070b12fd06426e Mon Sep 17 00:00:00 2001 +From 727728c9e456e4484ef8e1a05a66f78a90e1c24a Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:53:03 +0800 -Subject: [PATCH 10/14] ntsync +Subject: [PATCH 09/13] ntsync Signed-off-by: Eric Naim --- @@ -15694,10 +14662,10 @@ index 000000000000..767844637a7d + ``objs`` and in ``alert``. If this is attempted, the function fails + with ``EINVAL``. diff --git a/MAINTAINERS b/MAINTAINERS -index c27b4e8f2129..84ad898cd8f8 100644 +index 2ba00c0cd701..0bcfbc58a9ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -16336,6 +16336,15 @@ T: git https://github.com/Paragon-Software-Group/linux-ntfs3.git +@@ -16327,6 +16327,15 @@ T: git https://github.com/Paragon-Software-Group/linux-ntfs3.git F: Documentation/filesystems/ntfs3.rst F: fs/ntfs3/ @@ -18339,12 +17307,12 @@ index 000000000000..5fa2c9a0768c + +TEST_HARNESS_MAIN -- -2.47.0 +2.47.0.rc0 -From 700f445a288bd44318a6f1a941eb8547dc6313d5 Mon Sep 17 00:00:00 2001 +From 94b78b402e239cd15095fa2d3e07f99a060a4b45 Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:53:18 +0800 -Subject: [PATCH 11/14] perf-per-core +Subject: [PATCH 10/13] perf-per-core Signed-off-by: Eric Naim --- @@ -19199,7 +18167,7 @@ index b985ca79cf97..8206038a01ac 100644 } module_exit(intel_rapl_exit); diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h -index 9a28b11d0327..833dbb2170a6 100644 +index e17f4d733e44..7e53b701bc27 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -98,6 +98,7 @@ struct cpuinfo_topology { @@ -19211,7 +18179,7 @@ index 9a28b11d0327..833dbb2170a6 100644 // AMD Node ID and Nodes per Package info u32 amd_node_id; diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h -index 5b344ff81219..085611432c95 100644 +index 9f9376db64e3..1c55229efb1e 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -143,6 +143,7 @@ extern const struct cpumask *cpu_clustergroup_mask(int cpu); @@ -19223,11 +18191,11 @@ index 5b344ff81219..085611432c95 100644 #define topology_core_id(cpu) (cpu_data(cpu).topo.core_id) #define topology_ppin(cpu) (cpu_data(cpu).ppin) diff --git a/arch/x86/kernel/cpu/debugfs.c b/arch/x86/kernel/cpu/debugfs.c -index c3361e496df9..531727db9244 100644 +index 10719aba6276..cacfd3f6abef 100644 --- a/arch/x86/kernel/cpu/debugfs.c +++ b/arch/x86/kernel/cpu/debugfs.c @@ -25,6 +25,7 @@ static int cpu_debug_show(struct seq_file *m, void *p) - seq_printf(m, "cpu_type: %u\n", topology_cpu_type(c)); + seq_printf(m, "cpu_type: %s\n", get_topology_cpu_type_name(c)); seq_printf(m, "logical_pkg_id: %u\n", c->topo.logical_pkg_id); seq_printf(m, "logical_die_id: %u\n", c->topo.logical_die_id); + seq_printf(m, "logical_core_id: %u\n", c->topo.logical_core_id); @@ -19235,10 +18203,10 @@ index c3361e496df9..531727db9244 100644 seq_printf(m, "l2c_id: %u\n", c->topo.l2c_id); seq_printf(m, "amd_node_id: %u\n", c->topo.amd_node_id); diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/topology_common.c -index 04b012dffa47..fc4952ba1157 100644 +index 8277c64f88db..b5a5e1411469 100644 --- a/arch/x86/kernel/cpu/topology_common.c +++ b/arch/x86/kernel/cpu/topology_common.c -@@ -164,6 +164,7 @@ static void topo_set_ids(struct topo_scan *tscan, bool early) +@@ -185,6 +185,7 @@ static void topo_set_ids(struct topo_scan *tscan, bool early) if (!early) { c->topo.logical_pkg_id = topology_get_logical_id(apicid, TOPO_PKG_DOMAIN); c->topo.logical_die_id = topology_get_logical_id(apicid, TOPO_DIE_DOMAIN); @@ -19247,12 +18215,12 @@ index 04b012dffa47..fc4952ba1157 100644 /* Package relative core ID */ -- -2.47.0 +2.47.0.rc0 -From ffab2eb3364a202d5877a416e309303a2c76adc8 Mon Sep 17 00:00:00 2001 +From 38ca6249d4a3205988323759c2e0986d93e737aa Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:53:29 +0800 -Subject: [PATCH 12/14] t2 +Subject: [PATCH 11/13] t2 Signed-off-by: Eric Naim --- @@ -19410,10 +18378,10 @@ index 4451ef501936..c726a846f752 100644 ---- diff --git a/MAINTAINERS b/MAINTAINERS -index 84ad898cd8f8..94083f400734 100644 +index 0bcfbc58a9ab..affc58245cc1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -6912,6 +6912,12 @@ S: Supported +@@ -6903,6 +6903,12 @@ S: Supported T: git https://gitlab.freedesktop.org/drm/misc/kernel.git F: drivers/gpu/drm/sun4i/sun8i* @@ -29662,34 +28630,32 @@ index 4427572b2477..b60c99d61882 100755 last; } -- -2.47.0 +2.47.0.rc0 -From e6b7bcc3665414747dd2976d41a8b8f4f052dd77 Mon Sep 17 00:00:00 2001 +From 9c5f8134d6095a520bca8870f2477115b595ca07 Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:53:44 +0800 -Subject: [PATCH 13/14] thp-shrinker +Subject: [PATCH 12/13] thp-shrinker -Signed-off-by: Eric Naim +Signed-off-by: Peter Jung --- - Documentation/admin-guide/mm/transhuge.rst | 16 +++ + Documentation/admin-guide/mm/transhuge.rst | 16 ++ include/linux/huge_mm.h | 4 +- include/linux/khugepaged.h | 1 + include/linux/page-flags.h | 13 +- include/linux/rmap.h | 7 +- include/linux/vm_event_item.h | 1 + - mm/huge_memory.c | 124 ++++++++++++++++-- + mm/huge_memory.c | 143 ++++++++++++++++-- mm/khugepaged.c | 3 +- - mm/memcontrol.c | 3 +- - mm/migrate.c | 75 +++++++++-- + mm/migrate.c | 75 +++++++-- mm/migrate_device.c | 4 +- - mm/page_alloc.c | 5 +- mm/rmap.c | 5 +- mm/vmscan.c | 3 +- mm/vmstat.c | 1 + - .../selftests/mm/split_huge_page_test.c | 71 ++++++++++ - tools/testing/selftests/mm/vm_util.c | 22 ++++ + .../selftests/mm/split_huge_page_test.c | 71 +++++++++ + tools/testing/selftests/mm/vm_util.c | 22 +++ tools/testing/selftests/mm/vm_util.h | 1 + - 18 files changed, 323 insertions(+), 36 deletions(-) + 16 files changed, 334 insertions(+), 36 deletions(-) diff --git a/Documentation/admin-guide/mm/transhuge.rst b/Documentation/admin-guide/mm/transhuge.rst index 058485daf186..02ae7bc9efbd 100644 @@ -29830,7 +28796,7 @@ index 747943bc8cc2..d35e588e0ece 100644 THP_SCAN_EXCEED_NONE_PTE, THP_SCAN_EXCEED_SWAP_PTE, diff --git a/mm/huge_memory.c b/mm/huge_memory.c -index 4d2839fcf688..3292411ad8ed 100644 +index 4d2839fcf688..eb2e5c305547 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -77,6 +77,7 @@ static unsigned long deferred_split_count(struct shrinker *shrink, @@ -30026,6 +28992,17 @@ index 4d2839fcf688..3292411ad8ed 100644 static unsigned long deferred_split_scan(struct shrinker *shrink, struct shrink_control *sc) { +@@ -3369,8 +3442,8 @@ static unsigned long deferred_split_scan(struct shrinker *shrink, + struct deferred_split *ds_queue = &pgdata->deferred_split_queue; + unsigned long flags; + LIST_HEAD(list); +- struct folio *folio, *next; +- int split = 0; ++ struct folio *folio, *next, *prev = NULL; ++ int split = 0, removed = 0; + + #ifdef CONFIG_MEMCG + if (sc->memcg) @@ -3385,6 +3458,9 @@ static unsigned long deferred_split_scan(struct shrinker *shrink, list_move(&folio->_deferred_list, &list); } else { @@ -30036,7 +29013,7 @@ index 4d2839fcf688..3292411ad8ed 100644 list_del_init(&folio->_deferred_list); ds_queue->split_queue_len--; } -@@ -3394,13 +3470,35 @@ static unsigned long deferred_split_scan(struct shrinker *shrink, +@@ -3394,20 +3470,55 @@ static unsigned long deferred_split_scan(struct shrinker *shrink, spin_unlock_irqrestore(&ds_queue->split_queue_lock, flags); list_for_each_entry_safe(folio, next, &list, _deferred_list) { @@ -30060,6 +29037,7 @@ index 4d2839fcf688..3292411ad8ed 100644 + } folio_unlock(folio); next: +- folio_put(folio); + /* + * split_folio() removes folio from list on success. + * Only add back to the queue if folio is partially mapped. @@ -30069,11 +29047,31 @@ index 4d2839fcf688..3292411ad8ed 100644 + */ + if (!did_split && !folio_test_partially_mapped(folio)) { + list_del_init(&folio->_deferred_list); -+ ds_queue->split_queue_len--; ++ removed++; ++ } else { ++ /* ++ * That unlocked list_del_init() above would be unsafe, ++ * unless its folio is separated from any earlier folios ++ * left on the list (which may be concurrently unqueued) ++ * by one safe folio with refcount still raised. ++ */ ++ swap(folio, prev); + } - folio_put(folio); ++ if (folio) ++ folio_put(folio); } + spin_lock_irqsave(&ds_queue->split_queue_lock, flags); + list_splice_tail(&list, &ds_queue->split_queue); ++ ds_queue->split_queue_len -= removed; + spin_unlock_irqrestore(&ds_queue->split_queue_lock, flags); + ++ if (prev) ++ folio_put(prev); ++ + /* + * Stop shrinker if we didn't split any page, but the queue is empty. + * This can happen if pages were freed under us. diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 4cba91ecf74b..ee490f1e7de2 100644 --- a/mm/khugepaged.c @@ -30095,20 +29093,6 @@ index 4cba91ecf74b..ee490f1e7de2 100644 spin_unlock(pmd_ptl); folio = NULL; -diff --git a/mm/memcontrol.c b/mm/memcontrol.c -index d563fb515766..c5078e86ac55 100644 ---- a/mm/memcontrol.c -+++ b/mm/memcontrol.c -@@ -4606,7 +4606,8 @@ static void uncharge_folio(struct folio *folio, struct uncharge_gather *ug) - VM_BUG_ON_FOLIO(folio_test_lru(folio), folio); - VM_BUG_ON_FOLIO(folio_order(folio) > 1 && - !folio_test_hugetlb(folio) && -- !list_empty(&folio->_deferred_list), folio); -+ !list_empty(&folio->_deferred_list) && -+ folio_test_partially_mapped(folio), folio); - - /* - * Nobody should be changing or seriously looking at diff --git a/mm/migrate.c b/mm/migrate.c index 368ab3878fa6..d3a66f1a621b 100644 --- a/mm/migrate.c @@ -30276,22 +29260,6 @@ index 6d66dc1c6ffa..8f875636b35b 100644 folio_unlock(src); if (is_zone_device_page(page)) -diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index f8b4dae35fc3..6040ed48da3e 100644 ---- a/mm/page_alloc.c -+++ b/mm/page_alloc.c -@@ -962,8 +962,9 @@ static int free_tail_page_prepare(struct page *head_page, struct page *page) - break; - case 2: - /* the second tail page: deferred_list overlaps ->mapping */ -- if (unlikely(!list_empty(&folio->_deferred_list))) { -- bad_page(page, "on deferred list"); -+ if (unlikely(!list_empty(&folio->_deferred_list) && -+ folio_test_partially_mapped(folio))) { -+ bad_page(page, "partially mapped folio on deferred list"); - goto out; - } - break; diff --git a/mm/rmap.c b/mm/rmap.c index 2490e727e2dc..77b5185058b4 100644 --- a/mm/rmap.c @@ -30476,12 +29444,12 @@ index 9007c420d52c..2eaed8209925 100644 bool check_huge_file(void *addr, int nr_hpages, uint64_t hpage_size); bool check_huge_shmem(void *addr, int nr_hpages, uint64_t hpage_size); -- -2.47.0 +2.47.0.rc0 -From e4532e97539df2476624d56a4473c63350db44cc Mon Sep 17 00:00:00 2001 +From 6401d4b492055092a6ef1946c026e64ba06cc0ec Mon Sep 17 00:00:00 2001 From: Eric Naim Date: Tue, 22 Oct 2024 22:53:58 +0800 -Subject: [PATCH 14/14] zstd +Subject: [PATCH 13/13] zstd Signed-off-by: Eric Naim --- @@ -49128,4 +48096,4 @@ index f4ed952ed485..7d31518e9d5a 100644 EXPORT_SYMBOL(zstd_reset_dstream); -- -2.47.0 +2.47.0.rc0