From 2bdb0687d9427c2efdd7da1e13ede3a4e17f73fc Mon Sep 17 00:00:00 2001 From: "Dementiev, Roman" Date: Wed, 14 Oct 2026 15:33:04 +0200 Subject: [PATCH 1/4] Add WCL (Wildcat Lake) CPU support with family model 6, 213 Follow the PTL implementation: add the WCL enum, mark it supported, and add it to all PTL code paths (C-state tables, nominal frequency detection, TGLClientBW, hybrid core/atom event programming, fixed counter count, L2 miss/L3 snoop hit metrics). Report the codename as "Wildcat Lake". Change-Id: I749b712b1ce720cabf7bb64bf9ea4e736976fd3f Co-Authored-By: Claude Opus 5.5 --- src/cpucounters.cpp | 9 +++++++++ src/cpucounters.h | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/src/cpucounters.cpp b/src/cpucounters.cpp index 915f4aeb..943bfa09 100644 --- a/src/cpucounters.cpp +++ b/src/cpucounters.cpp @@ -865,6 +865,7 @@ void PCM::initCStateSupportTables() case LNL: case ARL: case PTL: + case WCL: PCM_CSTATE_ARRAY(pkgCStateMsr, PCM_PARAM_PROTECT({0, 0, 0x60D, 0x3F8, 0, 0, 0x3F9, 0x3FA, 0x630, 0x631, 0x632}) ); default: @@ -911,6 +912,7 @@ void PCM::initCStateSupportTables() case LNL: case ARL: case PTL: + case WCL: case CWF: case SNOWRIDGE: case ELKHART_LAKE: @@ -1468,6 +1470,7 @@ bool PCM::detectNominalFrequency() || cpu_family_model == LNL || cpu_family_model == ARL || cpu_family_model == PTL + || cpu_family_model == WCL || cpu_family_model == SKX || cpu_family_model == ICX || cpu_family_model == SPR @@ -2026,6 +2029,7 @@ void PCM::initUncoreObjects() case LNL: // TGLClientBW works fine for LNL case ARL: // TGLClientBW works fine for ARL case PTL: // TGLClientBW works fine for PTL + case WCL: // TGLClientBW works fine for WCL clientBW = std::make_shared(); break; /* Disabled since ADLClientBW requires 2x multiplier for BW on top @@ -3527,6 +3531,7 @@ bool PCM::isCPUModelSupported(const int model_) || model_ == LNL || model_ == ARL || model_ == PTL + || model_ == WCL || model_ == SKX || model_ == ICX || model_ == SPR @@ -3710,6 +3715,7 @@ PCM::ErrorCode PCM::program(const PCM::ProgramMode mode_, const void * parameter || cpu_family_model == LNL || cpu_family_model == ARL || cpu_family_model == PTL + || cpu_family_model == WCL )) { canUsePerf = false; @@ -3800,6 +3806,7 @@ PCM::ErrorCode PCM::program(const PCM::ProgramMode mode_, const void * parameter case LNL: case ARL: case PTL: + case WCL: LLCArchEventInit(hybridAtomEventDesc); hybridAtomEventDesc[2].event_number = SKL_MEM_LOAD_RETIRED_L2_MISS_EVTNR; hybridAtomEventDesc[2].umask_value = SKL_MEM_LOAD_RETIRED_L2_MISS_UMASK; @@ -5181,6 +5188,8 @@ const char * PCM::cpuFamilyModelToUArchCodename(const int32 cpu_family_model_, c return "Arrow Lake"; case PTL: return "Panther Lake"; + case WCL: + return "Wildcat Lake"; case SKX: if (cpu_stepping_ < 0) { diff --git a/src/cpucounters.h b/src/cpucounters.h index 552abb64..5818dc72 100644 --- a/src/cpucounters.h +++ b/src/cpucounters.h @@ -1838,6 +1838,7 @@ class PCM_API PCM case LNL: case ARL: case PTL: + case WCL: if (topology[coreID].core_type == TopologyEntry::Atom) { return eCoreOCREvent; @@ -1858,6 +1859,7 @@ class PCM_API PCM case LNL: case ARL: case PTL: + case WCL: useGLCOCREvent = true; break; @@ -2120,6 +2122,7 @@ class PCM_API PCM ARL = PCM_CPU_FAMILY_MODEL(6, 197), ARL_1 = PCM_CPU_FAMILY_MODEL(6, 198), PTL = PCM_CPU_FAMILY_MODEL(6, 204), + WCL = PCM_CPU_FAMILY_MODEL(6, 213), BDX = PCM_CPU_FAMILY_MODEL(6, 79), KNL = PCM_CPU_FAMILY_MODEL(6, 87), SKL = PCM_CPU_FAMILY_MODEL(6, 94), @@ -2378,6 +2381,7 @@ class PCM_API PCM case LNL: case ARL: case PTL: + case WCL: return 12; case CWF: return 8; @@ -2764,6 +2768,7 @@ class PCM_API PCM || cpu_family_model == PCM::LNL || cpu_family_model == PCM::ARL || cpu_family_model == PCM::PTL + || cpu_family_model == PCM::WCL || cpu_family_model == PCM::SPR || cpu_family_model == PCM::EMR || cpu_family_model == PCM::GNR @@ -2806,6 +2811,7 @@ class PCM_API PCM || cpu_family_model == PCM::LNL || cpu_family_model == PCM::ARL || cpu_family_model == PCM::PTL + || cpu_family_model == PCM::WCL || cpu_family_model == PCM::SPR || cpu_family_model == PCM::EMR || cpu_family_model == PCM::GNR @@ -3126,6 +3132,7 @@ class PCM_API PCM || cpu_family_model == LNL || cpu_family_model == ARL || cpu_family_model == PTL + || cpu_family_model == WCL || useSKLPath() ; } @@ -4804,6 +4811,7 @@ uint64 getL2CacheMisses(const CounterStateType & before, const CounterStateType || cpu_family_model == PCM::LNL || cpu_family_model == PCM::ARL || cpu_family_model == PCM::PTL + || cpu_family_model == PCM::WCL || cpu_family_model == PCM::CWF ) { return after.Event[BasicCounterState::SKLL2MissPos] - before.Event[BasicCounterState::SKLL2MissPos]; @@ -4922,6 +4930,7 @@ uint64 getL3CacheHitsSnoop(const CounterStateType & before, const CounterStateTy || cpu_family_model == PCM::LNL || cpu_family_model == PCM::ARL || cpu_family_model == PCM::PTL + || cpu_family_model == PCM::WCL || cpu_family_model == PCM::CWF ) { From 6a82b230bb6820249a2256a35a2baa57e6268a14 Mon Sep 17 00:00:00 2001 From: Roman Dementiev Date: Tue, 13 Oct 2026 13:37:01 +0200 Subject: [PATCH 2/4] Rename bhs-power-mode scripts to ufs-power-mode Co-Authored-By: Claude Opus 5.5 --- doc/LATENCY-OPTIMIZED-MODE.md | 12 ++++++------ scripts/{bhs-power-mode.ps1 => ufs-power-mode.ps1} | 0 scripts/{bhs-power-mode.sh => ufs-power-mode.sh} | 0 3 files changed, 6 insertions(+), 6 deletions(-) rename scripts/{bhs-power-mode.ps1 => ufs-power-mode.ps1} (100%) rename scripts/{bhs-power-mode.sh => ufs-power-mode.sh} (100%) diff --git a/doc/LATENCY-OPTIMIZED-MODE.md b/doc/LATENCY-OPTIMIZED-MODE.md index e7c629a2..fb53c398 100644 --- a/doc/LATENCY-OPTIMIZED-MODE.md +++ b/doc/LATENCY-OPTIMIZED-MODE.md @@ -23,8 +23,8 @@ Should this BIOS option be unavailable or if there is a preference to change the |Platform |Script Type| URL | |------------------|-----------|---------------------------------------------------------------------| -|Linux/FreeBSD/UNIX|bash | https://github.com/intel/pcm/blob/master/scripts/bhs-power-mode.sh | -|Windows |powershell | https://github.com/intel/pcm/blob/master/scripts/bhs-power-mode.ps1 | +|Linux/FreeBSD/UNIX|bash | https://github.com/intel/pcm/blob/master/scripts/ufs-power-mode.sh | +|Windows |powershell | https://github.com/intel/pcm/blob/master/scripts/ufs-power-mode.ps1 | The scripts require the pcm-tpmi utility. There are several methods to obtain this utility: - **Download or install precompiled PCM binaries:** Please refer to the following link: [Downloading Pre-Compiled PCM Tools](https://github.com/intel/pcm?tab=readme-ov-file#downloading-pre-compiled-pcm-tools) @@ -39,23 +39,23 @@ Once the pcm-tpmi binary is correctly placed, you can set the Latency Optimized Linux/FreeBSD/UNIX: ``` -bash bhs-power-mode.sh --latency-optimized-mode +bash ufs-power-mode.sh --latency-optimized-mode ``` Windows: ``` -.\bhs-power-mode.ps1 --latency-optimized-mode +.\ufs-power-mode.ps1 --latency-optimized-mode ``` ### Setting Optimized Power Mode Linux/FreeBSD/UNIX: ``` -bash bhs-power-mode.sh --optimized-power-mode +bash ufs-power-mode.sh --optimized-power-mode ``` Windows: ``` -.\bhs-power-mode.ps1 --optimized-power-mode +.\ufs-power-mode.ps1 --optimized-power-mode ``` diff --git a/scripts/bhs-power-mode.ps1 b/scripts/ufs-power-mode.ps1 similarity index 100% rename from scripts/bhs-power-mode.ps1 rename to scripts/ufs-power-mode.ps1 diff --git a/scripts/bhs-power-mode.sh b/scripts/ufs-power-mode.sh similarity index 100% rename from scripts/bhs-power-mode.sh rename to scripts/ufs-power-mode.sh From 6638d29d6e153984a7708c4304fde5239cb6ae41 Mon Sep 17 00:00:00 2001 From: Roman Dementiev Date: Tue, 13 Oct 2026 13:38:52 +0200 Subject: [PATCH 3/4] Rename Birch Stream to UFS (Uncore Frequency Scaling) in power mode scripts Co-Authored-By: Claude Opus 5.5 --- scripts/ufs-power-mode.ps1 | 2 +- scripts/ufs-power-mode.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ufs-power-mode.ps1 b/scripts/ufs-power-mode.ps1 index 488eb3dc..a3e20dfc 100644 --- a/scripts/ufs-power-mode.ps1 +++ b/scripts/ufs-power-mode.ps1 @@ -1,5 +1,5 @@ Write-Output "Intel(r) Performance Counter Monitor" -Write-Output "Birch Stream Power Mode Utility" +Write-Output "UFS (Uncore Frequency Scaling) Power Mode Utility" Write-Output "" Write-Output " Options:" diff --git a/scripts/ufs-power-mode.sh b/scripts/ufs-power-mode.sh index 988c6c40..17f10c27 100644 --- a/scripts/ufs-power-mode.sh +++ b/scripts/ufs-power-mode.sh @@ -1,7 +1,7 @@ #!/bin/bash echo "Intel(r) Performance Counter Monitor" -echo "Birch Stream Power Mode Utility" +echo "UFS (Uncore Frequency Scaling) Power Mode Utility" echo "" echo " Options:" From 0d3205b9d68c6501d653aac2e7a3171a3080824c Mon Sep 17 00:00:00 2001 From: Roman Dementiev Date: Tue, 13 Oct 2026 13:51:14 +0200 Subject: [PATCH 4/4] Show current UFS power mode when power mode scripts run without options Compare the EFFICIENCY_LATENCY_CTRL fields read from TPMI on all dies with the values written by --optimized-power-mode and --latency-optimized-mode and report Optimized Power Mode, Latency Optimized Mode or Unknown. Also fix the PowerShell script parsing of pcm-tpmi output (regex captures were never assigned) and read the register value as uint64 so that the IO die threshold fields above bit 31 are preserved. Co-Authored-By: Claude Opus 5.5 --- doc/LATENCY-OPTIMIZED-MODE.md | 14 +++++++++++ scripts/ufs-power-mode.ps1 | 44 +++++++++++++++++++++++++++++------ scripts/ufs-power-mode.sh | 29 +++++++++++++++++++++++ 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/doc/LATENCY-OPTIMIZED-MODE.md b/doc/LATENCY-OPTIMIZED-MODE.md index fb53c398..cbb0b262 100644 --- a/doc/LATENCY-OPTIMIZED-MODE.md +++ b/doc/LATENCY-OPTIMIZED-MODE.md @@ -59,3 +59,17 @@ Windows: ``` + +### Showing the Current Mode + +When run without options, the scripts read the TPMI registers and report the current mode (Optimized Power Mode, Latency Optimized Mode or Unknown if the register values on the dies do not match either mode): + +Linux/FreeBSD/UNIX: +``` +bash ufs-power-mode.sh +``` + +Windows: +``` +.\ufs-power-mode.ps1 +``` diff --git a/scripts/ufs-power-mode.ps1 b/scripts/ufs-power-mode.ps1 index a3e20dfc..21c0354f 100644 --- a/scripts/ufs-power-mode.ps1 +++ b/scripts/ufs-power-mode.ps1 @@ -5,6 +5,7 @@ Write-Output "" Write-Output " Options:" Write-Output " --optimized-power-mode : set optimized power mode" Write-Output " --latency-optimized-mode : set latency optimized mode" +Write-Output " (no option) : show the current mode" Write-Output "" # Run the pcm-tpmi command to determine I/O and compute dies @@ -19,8 +20,8 @@ $die_types = @{} $output -split "`n" | ForEach-Object { $line = $_ if ($line -match "entry" -and $line -match "instance") { - $entry = $line -match 'entry (\d+)' | Out-Null; $matches[1] - $instance = $line -match 'instance (\d+)' | Out-Null; $matches[1] + $entry = if ($line -match 'entry (\d+)') { $matches[1] } + $instance = if ($line -match 'instance (\d+)') { $matches[1] } $die_key = "${instance}:${entry}" if ($line -match "value 1") { $die_types[$die_key] = "IO" @@ -89,10 +90,14 @@ if ($args[0] -eq "--latency-optimized-mode") { Write-Output "Dumping TPMI Power control register states..." Write-Output "" +# Cleared when any die does not match the respective mode settings +$script:all_dies_optimized_power = $true +$script:all_dies_latency_optimized = $true + # Function to extract and calculate metrics from the value function ExtractAndPrintMetrics { param ( - [int]$value, + [uint64]$value, [int]$socket_id, [string]$die_key, [string]$numa_node, @@ -113,6 +118,18 @@ function ExtractAndPrintMetrics { $eff_latency_ctrl_high_threshold = ($value -shr 40) -band 0x7F $eff_latency_ctrl_high_threshold_enable = ($value -shr 39) -band 0x1 + # Compare raw register fields with the values written by the mode options above + $regs = "$eff_latency_ctrl_ratio" + $optimized_power_regs = "12" + $latency_optimized_regs = "0" + if ($die_type -eq "IO") { + $regs = "${eff_latency_ctrl_ratio}:${eff_latency_ctrl_low_threshold}:${eff_latency_ctrl_high_threshold}:${eff_latency_ctrl_high_threshold_enable}" + $optimized_power_regs = "8:13:120:1" + $latency_optimized_regs = "0:0:0:1" + } + if ($regs -ne $optimized_power_regs) { $script:all_dies_optimized_power = $false } + if ($regs -ne $latency_optimized_regs) { $script:all_dies_latency_optimized = $false } + # Convert to MHz or percentage $min_ratio = $min_ratio * 100 $max_ratio = $max_ratio * 100 @@ -148,9 +165,9 @@ foreach ($die_key in $die_types.Keys) { $output -split "`n" | ForEach-Object { $line = $_ if ($line -match "Read value") { - $value = $line -match 'value (\d+)' | Out-Null; $matches[1] - $inst = $line -match 'instance (\d+)' | Out-Null; $matches[1] - $ent = $line -match 'entry (\d+)' | Out-Null; $matches[1] + $value = if ($line -match 'value (\d+)') { $matches[1] } + $inst = if ($line -match 'instance (\d+)') { $matches[1] } + $ent = if ($line -match 'entry (\d+)') { $matches[1] } $parsed_die_key = "${inst}:${ent}" # Extract socket ID if present, otherwise fallback to instance ID if ($line -match '\(socket (\d+)\)') { @@ -166,4 +183,17 @@ foreach ($die_key in $die_types.Keys) { ExtractAndPrintMetrics -value $value -socket_id $socket_id -die_key $parsed_die_key -numa_node $numa_node -instance $inst } } -} \ No newline at end of file +} + +if ($args.Count -eq 0) { + if ($die_types.Count -eq 0) { + $current_mode = "Unknown" + } elseif ($script:all_dies_optimized_power) { + $current_mode = "Optimized Power Mode" + } elseif ($script:all_dies_latency_optimized) { + $current_mode = "Latency Optimized Mode" + } else { + $current_mode = "Unknown" + } + Write-Output "Current mode: $current_mode" +} diff --git a/scripts/ufs-power-mode.sh b/scripts/ufs-power-mode.sh index 17f10c27..13cd1fbe 100644 --- a/scripts/ufs-power-mode.sh +++ b/scripts/ufs-power-mode.sh @@ -7,6 +7,7 @@ echo "" echo " Options:" echo " --optimized-power-mode : set optimized power mode" echo " --latency-optimized-mode : set latency optimized mode" +echo " (no option) : show the current mode" echo # Run the pcm-tpmi command to determine I/O and compute dies @@ -92,6 +93,10 @@ fi echo "Dumping TPMI Power control register states..." echo "" +# Cleared when any die does not match the respective mode settings +all_dies_optimized_power=1 +all_dies_latency_optimized=1 + # Function to extract and calculate metrics from the value extract_and_print_metrics() { local value=$1 @@ -113,6 +118,18 @@ extract_and_print_metrics() { local eff_latency_ctrl_high_threshold=$(( (value >> 40) & 0x7F )) local eff_latency_ctrl_high_threshold_enable=$(( (value >> 39) & 0x1 )) + # Compare raw register fields with the values written by the mode options above + local regs="$eff_latency_ctrl_ratio" + local optimized_power_regs="12" + local latency_optimized_regs="0" + if [ "$die_type" == "IO" ] ; then + regs="$eff_latency_ctrl_ratio:$eff_latency_ctrl_low_threshold:$eff_latency_ctrl_high_threshold:$eff_latency_ctrl_high_threshold_enable" + optimized_power_regs="8:13:120:1" + latency_optimized_regs="0:0:0:1" + fi + [ "$regs" != "$optimized_power_regs" ] && all_dies_optimized_power=0 + [ "$regs" != "$latency_optimized_regs" ] && all_dies_latency_optimized=0 + # Convert to MHz or percentage min_ratio=$(( min_ratio * 100 )) max_ratio=$(( max_ratio * 100 )) @@ -169,3 +186,15 @@ for die_key in "${!die_types[@]}"; do done <<< "$output" done +if [ -z "$1" ]; then + if [ ${#die_types[@]} -eq 0 ]; then + current_mode="Unknown" + elif [ $all_dies_optimized_power -eq 1 ]; then + current_mode="Optimized Power Mode" + elif [ $all_dies_latency_optimized -eq 1 ]; then + current_mode="Latency Optimized Mode" + else + current_mode="Unknown" + fi + echo "Current mode: $current_mode" +fi