From 4d1827485acecac0016eaaec199e97697afdaa84 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 31 Jul 2023 14:02:11 +0800 Subject: tools/power/turbostat: Fix failure with new uncore sysfs On some platforms, turbostat fails during launch time like below, turbostat version 2023.03.17 - Len Brown ... cpu40: MSR_IA32_PACKAGE_THERM_STATUS: 0x884c0000 (24 C) cpu40: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x00000003 (100 C, 100 C) turbostat: snapshot_sysfs_counter(/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz): No data available This is because new uncore sysfs is used on these platforms as introduced by commit 9b8dea80e3cb ("platform/x86/intel-uncore-freq: Support for cluster level controls"). With the new uncore sysfs interface, /sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz is still available, but reading it fails. How to support the fabric cluster level uncore sysfs is not settled yet, as a short term fix, clear the BIC_UNCORE_MHZ bit when new sysfs I/F is detected. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 9a10512e3407..9de1ff6f82ce 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4163,6 +4163,10 @@ static void intel_uncore_frequency_probe(void) if (access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00", R_OK)) return; + /* Cluster level sysfs not supported yet. */ + if (!access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00", R_OK)) + return; + if (!access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz", R_OK)) BIC_PRESENT(BIC_UNCORE_MHZ); -- cgit v1.2.3 From 137f01b3529d292a68d22e9681e2f903c768f790 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 25 Mar 2023 21:57:07 +0800 Subject: tools/power/turbostat: Fix a knl bug MSR_KNL_CORE_C6_RESIDENCY should be evaluated only if 1. this is KNL platform AND 2. need to get C6 residency or need to calculate C1 residency Fix the broken logic introduced by commit 1e9042b9c8d4 ("tools/power turbostat: Fix CPU%C1 display value"). Fixes: 1e9042b9c8d4 ("tools/power turbostat: Fix CPU%C1 display value") Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 9de1ff6f82ce..fb6c6ddbdb60 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2180,7 +2180,7 @@ retry: if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) { if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6)) return -7; - } else if (do_knl_cstates || soft_c1_residency_display(BIC_CPU_c6)) { + } else if (do_knl_cstates && soft_c1_residency_display(BIC_CPU_c6)) { if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6)) return -7; } -- cgit v1.2.3 From b61b7d8c4c22c4298a50ae5d0ee88facb85ce665 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Mon, 27 Mar 2023 11:17:44 +0800 Subject: tools/power/turbostat: Enable the C-state Pre-wake printing Currently the C-state Pre-wake will not be printed due to the probe has not been invoked. Invoke the probe function accordingly. Fixes: aeb01e6d71ff ("tools/power turbostat: Print the C-state Pre-wake settings") Signed-off-by: Chen Yu Reviewed-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index fb6c6ddbdb60..03d4f09b103a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5794,6 +5794,7 @@ void process_cpuid() rapl_probe(family, model); perf_limit_reasons_probe(family, model); automatic_cstate_conversion_probe(family, model); + prewake_cstate_probe(family, model); check_tcc_offset(model_orig); -- cgit v1.2.3 From b98a6d78768ec459d394db8bc086d071eb6556c8 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 24 Mar 2023 16:30:55 +0800 Subject: tools/power/turbostat: Enable TCC Offset on more models All Models that duplicate INTEL_FAM6_CANNONLAKE_L support TCC Offset. Enable this feature on all these models. Delete obsolete model_orig. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 03d4f09b103a..d7880870ef68 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -211,9 +211,6 @@ int *fd_instr_count_percpu; struct timeval interval_tv = { 5, 0 }; struct timespec interval_ts = { 5, 0 }; -/* Save original CPU model */ -unsigned int model_orig; - unsigned int num_iterations; unsigned int header_iterations; unsigned int debug; @@ -4046,14 +4043,7 @@ void check_tcc_offset(int model) switch (model) { case INTEL_FAM6_SKYLAKE_L: - case INTEL_FAM6_SKYLAKE: - case INTEL_FAM6_KABYLAKE_L: - case INTEL_FAM6_KABYLAKE: - case INTEL_FAM6_ICELAKE_L: - case INTEL_FAM6_ICELAKE: - case INTEL_FAM6_TIGERLAKE_L: - case INTEL_FAM6_TIGERLAKE: - case INTEL_FAM6_COMETLAKE: + case INTEL_FAM6_CANNONLAKE_L: if (!get_msr(base_cpu, MSR_PLATFORM_INFO, &msr)) { msr = (msr >> 30) & 1; if (msr) @@ -5573,10 +5563,9 @@ void process_cpuid() edx_flags & (1 << 22) ? "ACPI-TM" : "-", edx_flags & (1 << 28) ? "HT" : "-", edx_flags & (1 << 29) ? "TM" : "-"); } - if (genuine_intel) { - model_orig = model; + + if (genuine_intel) model = intel_model_duplicates(model); - } if (!(edx_flags & (1 << 5))) errx(1, "CPUID: no MSR"); @@ -5796,7 +5785,7 @@ void process_cpuid() automatic_cstate_conversion_probe(family, model); prewake_cstate_probe(family, model); - check_tcc_offset(model_orig); + check_tcc_offset(model); if (!quiet) dump_cstate_pstate_config_info(family, model); -- cgit v1.2.3 From 2c019d657968bdd93e11615e0919d8181a54742d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 21 Aug 2022 22:39:16 +0800 Subject: tools/power/turbostat: Support alternative graphics sysfs knobs /sys/class/graphics/fb0/device/drm/card0/ and /sys/class/drm/card0/ point to the same device node. But in some cases, one exists and the other one does not. Prefer to use /sys/class/drm/card0/, and fall back to /sys/class/graphics/fb0/device/drm/card0/. This recovers the "GFXMHz" and "GFXAMHz" columns on some platforms like a SPR server. Reviewed-by: Rodrigo Vivi Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index d7880870ef68..f9bc2230db73 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -3188,8 +3188,8 @@ int snapshot_gfx_rc6_ms(void) /* * snapshot_gfx_mhz() * - * record snapshot of - * /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz + * fall back to /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz + * when /sys/class/drm/card0/gt_cur_freq_mhz is not available. * * return 1 if config change requires a restart, else return 0 */ @@ -3198,9 +3198,11 @@ int snapshot_gfx_mhz(void) static FILE *fp; int retval; - if (fp == NULL) - fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r"); - else { + if (fp == NULL) { + fp = fopen("/sys/class/drm/card0/gt_cur_freq_mhz", "r"); + if (!fp) + fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r"); + } else { rewind(fp); fflush(fp); } @@ -3215,8 +3217,8 @@ int snapshot_gfx_mhz(void) /* * snapshot_gfx_cur_mhz() * - * record snapshot of - * /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz + * fall back to /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz + * when /sys/class/drm/card0/gt_act_freq_mhz is not available. * * return 1 if config change requires a restart, else return 0 */ @@ -3225,9 +3227,11 @@ int snapshot_gfx_act_mhz(void) static FILE *fp; int retval; - if (fp == NULL) - fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r"); - else { + if (fp == NULL) { + fp = fopen("/sys/class/drm/card0/gt_act_freq_mhz", "r"); + if (!fp) + fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r"); + } else { rewind(fp); fflush(fp); } @@ -5804,10 +5808,12 @@ void process_cpuid() if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) BIC_PRESENT(BIC_GFX_rc6); - if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK)) + if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK) || + !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK)) BIC_PRESENT(BIC_GFXMHz); - if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK)) + if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK) || + !access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK)) BIC_PRESENT(BIC_GFXACTMHz); if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK)) -- cgit v1.2.3 From 6d306d6ec7e0f9a5e90f5afd70e3b6c32ae50ce6 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 24 Mar 2023 16:26:25 +0800 Subject: tools/power/turbostat: Replace raw value cpu model with Macro Kernel already has #define INTEL_FAM6_NEHALEM_G 0x1F /* Auburndale / Havendale */ Use standard Macro for CPU Model instead of raw value. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index f9bc2230db73..8d3a8af3692a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5413,7 +5413,7 @@ unsigned int intel_model_duplicates(unsigned int model) switch (model) { case INTEL_FAM6_NEHALEM_EP: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */ case INTEL_FAM6_NEHALEM: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */ - case 0x1F: /* Core i7 and i5 Processor - Nehalem */ + case INTEL_FAM6_NEHALEM_G: /* Core i7 and i5 Processor - Nehalem */ case INTEL_FAM6_WESTMERE: /* Westmere Client - Clarkdale, Arrandale */ case INTEL_FAM6_WESTMERE_EP: /* Westmere EP - Gulftown */ return INTEL_FAM6_NEHALEM; -- cgit v1.2.3 From bbfc33b1e49f443296e56d8b76c77373f700aedc Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 24 Mar 2023 16:27:30 +0800 Subject: tools/power/turbostat: Remove redundant duplicates Remove redundant duplicates in intel_model_duplicates(). Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 8d3a8af3692a..2420300939da 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5412,24 +5412,20 @@ unsigned int intel_model_duplicates(unsigned int model) switch (model) { case INTEL_FAM6_NEHALEM_EP: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */ - case INTEL_FAM6_NEHALEM: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */ case INTEL_FAM6_NEHALEM_G: /* Core i7 and i5 Processor - Nehalem */ case INTEL_FAM6_WESTMERE: /* Westmere Client - Clarkdale, Arrandale */ case INTEL_FAM6_WESTMERE_EP: /* Westmere EP - Gulftown */ return INTEL_FAM6_NEHALEM; - case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ case INTEL_FAM6_WESTMERE_EX: /* Westmere-EX Xeon - Eagleton */ return INTEL_FAM6_NEHALEM_EX; case INTEL_FAM6_XEON_PHI_KNM: return INTEL_FAM6_XEON_PHI_KNL; - case INTEL_FAM6_BROADWELL_X: case INTEL_FAM6_BROADWELL_D: /* BDX-DE */ return INTEL_FAM6_BROADWELL_X; - case INTEL_FAM6_SKYLAKE_L: case INTEL_FAM6_SKYLAKE: case INTEL_FAM6_KABYLAKE_L: case INTEL_FAM6_KABYLAKE: -- cgit v1.2.3 From 48674c1bb6124fe392e8fed80a39fcb3f62e6551 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 27 Mar 2023 12:36:55 +0800 Subject: tools/power/turbostat: Remove pseudo check for two models INTEL_FAM6_ATOM_SILVERMONT_MID/INTEL_FAM6_ATOM_AIRMONT_MID are not listed in probe_nhm_msrs(). This means that most of the turbostat features are not available on these two platforms. Further more, checking for these two models in has_slv_msrs() is dead code. Because has_slv_msrs() is called by the code guarded by probe_nhm_msrs(). For these two reasons, remove pseudo check for INTEL_FAM6_ATOM_SILVERMONT_MID and INTEL_FAM6_ATOM_AIRMONT_MID. Will add back the support when we can access these two platforms. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 2420300939da..b8874d3dc83e 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -3792,8 +3792,6 @@ int has_slv_msrs(unsigned int family, unsigned int model) switch (model) { case INTEL_FAM6_ATOM_SILVERMONT: - case INTEL_FAM6_ATOM_SILVERMONT_MID: - case INTEL_FAM6_ATOM_AIRMONT_MID: return 1; } return 0; -- cgit v1.2.3 From 45232ab168a3c5abad86eafaef2beed8d7037666 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 21:52:53 +0800 Subject: tools/power/turbostat: Add skeleton support for table driven feature enumeration Turbostat supports a series of features that may diverge among different CPU models. Current code uses various of CPU model checks in different places to handle this, which makes the code hard to maintain. Add skeleton support for table driven feature enumeration to replace the current error-prone CPU model checks and global variables. Note: by comparing the CPU models with intel-family.h, it is found that turbostat support for below four Models are missing, including INTEL_FAM6_ICELAKE, INTEL_FAM6_ATOM_SILVERMONT_MID, INTEL_FAM6_ATOM_AIRMONT_MID and INTEL_FAM6_ATOM_AIRMONT_NP. Adding support for these models is a different work, thus it is not covered in this patch set. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 192 ++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index b8874d3dc83e..4deea374188a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -281,6 +281,197 @@ unsigned int has_misc_feature_control; unsigned int first_counter_read = 1; int ignore_stdin; +/* Model specific support Start */ + +/* List of features that may diverge among different platforms */ +struct platform_features { +}; + +struct platform_data { + unsigned int model; + const struct platform_features *features; +}; + +static const struct platform_features nhm_features = { +}; + +static const struct platform_features nhx_features = { +}; + +static const struct platform_features snb_features = { +}; + +static const struct platform_features snx_features = { +}; + +static const struct platform_features ivb_features = { +}; + +static const struct platform_features ivx_features = { +}; + +static const struct platform_features hsw_features = { +}; + +static const struct platform_features hsx_features = { +}; + +static const struct platform_features hswl_features = { +}; + +static const struct platform_features hswg_features = { +}; + +static const struct platform_features bdw_features = { +}; + +static const struct platform_features bdwg_features = { +}; + +static const struct platform_features bdx_features = { +}; + +static const struct platform_features skl_features = { +}; + +static const struct platform_features cnl_features = { +}; + +static const struct platform_features skx_features = { +}; + +static const struct platform_features icx_features = { +}; + +static const struct platform_features spr_features = { +}; + +static const struct platform_features slv_features = { +}; + +static const struct platform_features slvd_features = { +}; + +static const struct platform_features amt_features = { +}; + +static const struct platform_features gmt_features = { +}; + +static const struct platform_features gmtd_features = { +}; + +static const struct platform_features gmtp_features = { +}; + +static const struct platform_features tmt_features = { +}; + +static const struct platform_features tmtd_features = { +}; + +static const struct platform_features knl_features = { +}; + +static const struct platform_features default_features = { +}; + +static const struct platform_features amd_features = { +}; + +static const struct platform_data turbostat_pdata[] = { + { INTEL_FAM6_NEHALEM, &nhm_features }, + { INTEL_FAM6_NEHALEM_G, &nhm_features }, + { INTEL_FAM6_NEHALEM_EP, &nhm_features }, + { INTEL_FAM6_NEHALEM_EX, &nhx_features }, + { INTEL_FAM6_WESTMERE, &nhm_features }, + { INTEL_FAM6_WESTMERE_EP, &nhm_features }, + { INTEL_FAM6_WESTMERE_EX, &nhx_features }, + { INTEL_FAM6_SANDYBRIDGE, &snb_features }, + { INTEL_FAM6_SANDYBRIDGE_X, &snx_features }, + { INTEL_FAM6_IVYBRIDGE, &ivb_features }, + { INTEL_FAM6_IVYBRIDGE_X, &ivx_features }, + { INTEL_FAM6_HASWELL, &hsw_features }, + { INTEL_FAM6_HASWELL_X, &hsx_features }, + { INTEL_FAM6_HASWELL_L, &hswl_features }, + { INTEL_FAM6_HASWELL_G, &hswg_features }, + { INTEL_FAM6_BROADWELL, &bdw_features }, + { INTEL_FAM6_BROADWELL_G, &bdwg_features }, + { INTEL_FAM6_BROADWELL_X, &bdx_features }, + { INTEL_FAM6_BROADWELL_D, &bdx_features }, + { INTEL_FAM6_SKYLAKE_L, &skl_features }, + { INTEL_FAM6_SKYLAKE, &skl_features }, + { INTEL_FAM6_SKYLAKE_X, &skx_features }, + { INTEL_FAM6_KABYLAKE_L, &skl_features }, + { INTEL_FAM6_KABYLAKE, &skl_features }, + { INTEL_FAM6_COMETLAKE, &skl_features }, + { INTEL_FAM6_COMETLAKE_L, &skl_features }, + { INTEL_FAM6_CANNONLAKE_L, &cnl_features }, + { INTEL_FAM6_ICELAKE_X, &icx_features }, + { INTEL_FAM6_ICELAKE_D, &icx_features }, + { INTEL_FAM6_ICELAKE_L, &cnl_features }, + { INTEL_FAM6_ICELAKE_NNPI, &cnl_features }, + { INTEL_FAM6_ROCKETLAKE, &cnl_features }, + { INTEL_FAM6_TIGERLAKE_L, &cnl_features }, + { INTEL_FAM6_TIGERLAKE, &cnl_features }, + { INTEL_FAM6_SAPPHIRERAPIDS_X, &spr_features }, + { INTEL_FAM6_EMERALDRAPIDS_X, &spr_features }, + { INTEL_FAM6_LAKEFIELD, &cnl_features }, + { INTEL_FAM6_ALDERLAKE, &cnl_features }, + { INTEL_FAM6_ALDERLAKE_L, &cnl_features }, + { INTEL_FAM6_RAPTORLAKE, &cnl_features }, + { INTEL_FAM6_RAPTORLAKE_P, &cnl_features }, + { INTEL_FAM6_RAPTORLAKE_S, &cnl_features }, + { INTEL_FAM6_METEORLAKE, &cnl_features }, + { INTEL_FAM6_METEORLAKE_L, &cnl_features }, + { INTEL_FAM6_ATOM_SILVERMONT, &slv_features }, + { INTEL_FAM6_ATOM_SILVERMONT_D, &slvd_features }, + { INTEL_FAM6_ATOM_AIRMONT, &amt_features }, + { INTEL_FAM6_ATOM_GOLDMONT, &gmt_features }, + { INTEL_FAM6_ATOM_GOLDMONT_D, &gmtd_features }, + { INTEL_FAM6_ATOM_GOLDMONT_PLUS, &gmtp_features }, + { INTEL_FAM6_ATOM_TREMONT_D, &tmtd_features }, + { INTEL_FAM6_ATOM_TREMONT, &tmt_features }, + { INTEL_FAM6_ATOM_TREMONT_L, &tmt_features }, + { INTEL_FAM6_ATOM_GRACEMONT, &cnl_features }, + { INTEL_FAM6_XEON_PHI_KNL, &knl_features }, + { INTEL_FAM6_XEON_PHI_KNM, &knl_features }, + /* + * Missing support for + * INTEL_FAM6_ICELAKE + * INTEL_FAM6_ATOM_SILVERMONT_MID + * INTEL_FAM6_ATOM_AIRMONT_MID + * INTEL_FAM6_ATOM_AIRMONT_NP + */ + { 0, NULL }, +}; + +static const struct platform_features *platform; + +void probe_platform_features(unsigned int family, unsigned int model) +{ + int i; + + if (authentic_amd || hygon_genuine) { + platform = &amd_features; + return; + } + + platform = &default_features; + + if (!genuine_intel || family != 6) + return; + + for (i = 0; turbostat_pdata[i].features; i++) { + if (turbostat_pdata[i].model == model) { + platform = turbostat_pdata[i].features; + return; + } + } +} + +/* Model specific support End */ + #define RAPL_PKG (1 << 0) /* 0x610 MSR_PKG_POWER_LIMIT */ /* 0x611 MSR_PKG_ENERGY_STATUS */ @@ -5562,6 +5753,7 @@ void process_cpuid() edx_flags & (1 << 28) ? "HT" : "-", edx_flags & (1 << 29) ? "TM" : "-"); } + probe_platform_features(family, model); if (genuine_intel) model = intel_model_duplicates(model); -- cgit v1.2.3 From 778fc34a7a3db2811e28ce570318dd047f278cb2 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 21 Aug 2023 15:26:32 +0800 Subject: tools/power/turbostat: Abstract MSR_MISC_FEATURE_CONTROL support Abstract MSR_MISC_FEATURE_CONTROL support. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 4deea374188a..7eaa0adf72e0 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -277,7 +277,6 @@ unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */ unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ -unsigned int has_misc_feature_control; unsigned int first_counter_read = 1; int ignore_stdin; @@ -285,6 +284,7 @@ int ignore_stdin; /* List of features that may diverge among different platforms */ struct platform_features { + bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */ }; struct platform_data { @@ -299,51 +299,67 @@ static const struct platform_features nhx_features = { }; static const struct platform_features snb_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features snx_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features ivb_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features ivx_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features hsw_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features hsx_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features hswl_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features hswg_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features bdw_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features bdwg_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features bdx_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features skl_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features cnl_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features skx_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features icx_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features spr_features = { + .has_msr_misc_feature_control = 1, }; static const struct platform_features slv_features = { @@ -3883,7 +3899,6 @@ void check_permissions(void) * * Side effect: * sets global pkg_cstate_limit to decode MSR_PKG_CST_CONFIG_CONTROL - * sets has_misc_feature_control */ int probe_nhm_msrs(unsigned int family, unsigned int model) { @@ -3909,7 +3924,6 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) case INTEL_FAM6_IVYBRIDGE: /* IVB */ case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ pkg_cstate_limits = snb_pkg_cstate_limits; - has_misc_feature_control = 1; break; case INTEL_FAM6_HASWELL: /* HSW */ case INTEL_FAM6_HASWELL_G: /* HSW */ @@ -3921,16 +3935,13 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) case INTEL_FAM6_SKYLAKE_L: /* SKL */ case INTEL_FAM6_CANNONLAKE_L: /* CNL */ pkg_cstate_limits = hsw_pkg_cstate_limits; - has_misc_feature_control = 1; break; case INTEL_FAM6_SKYLAKE_X: /* SKX */ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ pkg_cstate_limits = skx_pkg_cstate_limits; - has_misc_feature_control = 1; break; case INTEL_FAM6_ICELAKE_X: /* ICX */ pkg_cstate_limits = icx_pkg_cstate_limits; - has_misc_feature_control = 1; break; case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ no_MSR_MISC_PWR_MGMT = 1; @@ -5541,7 +5552,7 @@ void decode_misc_feature_control(void) { unsigned long long msr; - if (!has_misc_feature_control) + if (!platform->has_msr_misc_feature_control) return; if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr)) -- cgit v1.2.3 From 3dd0e7547d11e770bafb40ad41f2631cc4b16649 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 21 Aug 2023 22:12:57 +0800 Subject: tools/power/turbostat: Abstract MSR_MISC_PWR_MGMT support Abstract MSR_MISC_PWR_MGMT support. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 7eaa0adf72e0..9507f310e212 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -238,7 +238,6 @@ unsigned int hygon_genuine; unsigned int max_level, max_extended_level; unsigned int has_invariant_tsc; unsigned int do_nhm_platform_info; -unsigned int no_MSR_MISC_PWR_MGMT; unsigned int aperf_mperf_multiplier = 1; double bclk; double base_hz; @@ -285,6 +284,7 @@ int ignore_stdin; /* List of features that may diverge among different platforms */ struct platform_features { bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */ + bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */ }; struct platform_data { @@ -293,100 +293,125 @@ struct platform_data { }; static const struct platform_features nhm_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features nhx_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features snb_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features snx_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features ivb_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features ivx_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features hsw_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features hsx_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features hswl_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features hswg_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features bdw_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features bdwg_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features bdx_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features skl_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features cnl_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features skx_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features icx_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features spr_features = { .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features slv_features = { }; static const struct platform_features slvd_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features amt_features = { }; static const struct platform_features gmt_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features gmtd_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features gmtp_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features tmt_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features tmtd_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features knl_features = { + .has_msr_misc_pwr_mgmt = 1, }; static const struct platform_features default_features = { @@ -3944,14 +3969,12 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) pkg_cstate_limits = icx_pkg_cstate_limits; break; case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ - no_MSR_MISC_PWR_MGMT = 1; /* FALLTHRU */ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ pkg_cstate_limits = slv_pkg_cstate_limits; break; case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ pkg_cstate_limits = amt_pkg_cstate_limits; - no_MSR_MISC_PWR_MGMT = 1; break; case INTEL_FAM6_XEON_PHI_KNL: /* PHI */ pkg_cstate_limits = phi_pkg_cstate_limits; @@ -5576,7 +5599,7 @@ void decode_misc_pwr_mgmt_msr(void) if (!do_nhm_platform_info) return; - if (no_MSR_MISC_PWR_MGMT) + if (!platform->has_msr_misc_pwr_mgmt) return; if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr)) -- cgit v1.2.3 From 71e841293c715797d8c6ae8cdc3f74b4396c5570 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 21 Aug 2023 22:22:48 +0800 Subject: tools/power/turbostat: Abstract BCLK frequency support Abstract CPU base clock frequency support. Note that bclk is used by 1. calculate base_hz using MSR_PLATFORM_INFO, which is guarded by probe_nhm_msrs(). 2. dump MSR_PLATFORM_INFO and Turbo Ratio Limit MSRs, which are also guarded by probe_nhm_msrs(). Thus probe_bclk() works for probe_nhm_msrs() models only. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 131 ++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 44 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 9507f310e212..66ba70017d53 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -269,7 +269,6 @@ unsigned int do_ring_perf_limit_reasons; unsigned int crystal_hz; unsigned long long tsc_hz; int base_cpu; -double discover_bclk(unsigned int family, unsigned int model); unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */ /* IA32_HWP_REQUEST, IA32_HWP_STATUS */ unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */ @@ -279,12 +278,15 @@ unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ unsigned int first_counter_read = 1; int ignore_stdin; +int get_msr(int cpu, off_t offset, unsigned long long *msr); + /* Model specific support Start */ /* List of features that may diverge among different platforms */ struct platform_features { bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */ bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */ + int bclk_freq; /* CPU base clock */ }; struct platform_data { @@ -292,126 +294,185 @@ struct platform_data { const struct platform_features *features; }; +/* For BCLK */ +enum bclk_freq { + BCLK_100MHZ = 1, + BCLK_133MHZ, + BCLK_SLV, +}; + +#define SLM_BCLK_FREQS 5 +double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0 }; + +double slm_bclk(void) +{ + unsigned long long msr = 3; + unsigned int i; + double freq; + + if (get_msr(base_cpu, MSR_FSB_FREQ, &msr)) + fprintf(outf, "SLM BCLK: unknown\n"); + + i = msr & 0xf; + if (i >= SLM_BCLK_FREQS) { + fprintf(outf, "SLM BCLK[%d] invalid\n", i); + i = 3; + } + freq = slm_freq_table[i]; + + if (!quiet) + fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq); + + return freq; +} + static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_133MHZ, }; static const struct platform_features nhx_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_133MHZ, }; static const struct platform_features snb_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features snx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features ivb_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features ivx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features hsw_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features hsx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features hswl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features hswg_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features bdw_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features bdwg_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features bdx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features skl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features cnl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features skx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features icx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features spr_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features slv_features = { + .bclk_freq = BCLK_SLV, }; static const struct platform_features slvd_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_SLV, }; static const struct platform_features amt_features = { + .bclk_freq = BCLK_133MHZ, }; static const struct platform_features gmt_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features gmtd_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features gmtp_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features tmtd_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features knl_features = { .has_msr_misc_pwr_mgmt = 1, + .bclk_freq = BCLK_100MHZ, }; static const struct platform_features default_features = { @@ -3907,6 +3968,30 @@ void check_permissions(void) exit(-6); } +void probe_bclk(void) +{ + unsigned long long msr; + unsigned int base_ratio; + + if (!do_nhm_platform_info) + return; + + if (platform->bclk_freq == BCLK_100MHZ) + bclk = 100.00; + else if (platform->bclk_freq == BCLK_133MHZ) + bclk = 133.33; + else if (platform->bclk_freq == BCLK_SLV) + bclk = slm_bclk(); + else + return; + + get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); + base_ratio = (msr >> 8) & 0xFF; + + base_hz = base_ratio * bclk * 1000000; + has_base_hz = 1; +} + /* * NHM adds support for additional MSRs: * @@ -3928,7 +4013,6 @@ void check_permissions(void) int probe_nhm_msrs(unsigned int family, unsigned int model) { unsigned long long msr; - unsigned int base_ratio; int *pkg_cstate_limits; if (!genuine_intel) @@ -3937,8 +4021,6 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) if (family != 6) return 0; - bclk = discover_bclk(family, model); - switch (model) { case INTEL_FAM6_NEHALEM: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */ case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ @@ -3992,11 +4074,6 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr); pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; - get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); - base_ratio = (msr >> 8) & 0xFF; - - base_hz = base_ratio * bclk * 1000000; - has_base_hz = 1; return 1; } @@ -5403,41 +5480,6 @@ unsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model) return 1; } -#define SLM_BCLK_FREQS 5 -double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0 }; - -double slm_bclk(void) -{ - unsigned long long msr = 3; - unsigned int i; - double freq; - - if (get_msr(base_cpu, MSR_FSB_FREQ, &msr)) - fprintf(outf, "SLM BCLK: unknown\n"); - - i = msr & 0xf; - if (i >= SLM_BCLK_FREQS) { - fprintf(outf, "SLM BCLK[%d] invalid\n", i); - i = 3; - } - freq = slm_freq_table[i]; - - if (!quiet) - fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq); - - return freq; -} - -double discover_bclk(unsigned int family, unsigned int model) -{ - if (has_snb_msrs(family, model) || is_knl(family, model)) - return 100.00; - else if (is_slm(family, model)) - return slm_bclk(); - else - return 133.33; -} - int get_cpu_type(struct thread_data *t, struct core_data *c, struct pkg_data *p) { unsigned int eax, ebx, ecx, edx; @@ -5929,6 +5971,7 @@ void process_cpuid() BIC_PRESENT(BIC_CPU_c6); BIC_PRESENT(BIC_SMI); } + probe_bclk(); do_snb_cstates = has_snb_msrs(family, model); if (do_snb_cstates) -- cgit v1.2.3 From 3989fc890782c8002477895e9f24ffb98a132293 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 22:37:06 +0800 Subject: tools/power/turbostat: Abstract Package cstate limit decoding support Abstract the support for decoding package cstate limit from MSR_PKG_CST_CONFIG_CONTROL. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 112 ++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 26 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 66ba70017d53..bcad9332a3b2 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -287,6 +287,7 @@ struct platform_features { bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */ bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */ int bclk_freq; /* CPU base clock */ + int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ }; struct platform_data { @@ -326,153 +327,193 @@ double slm_bclk(void) return freq; } +/* For Package cstate limit */ +enum package_cstate_limit { + CST_LIMIT_NHM = 1, + CST_LIMIT_SNB, + CST_LIMIT_HSW, + CST_LIMIT_SKX, + CST_LIMIT_ICX, + CST_LIMIT_SLV, + CST_LIMIT_AMT, + CST_LIMIT_KNL, + CST_LIMIT_GMT, +}; + static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_133MHZ, + .cst_limit = CST_LIMIT_NHM, }; static const struct platform_features nhx_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_133MHZ, + .cst_limit = CST_LIMIT_NHM, }; static const struct platform_features snb_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_SNB, }; static const struct platform_features snx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_SNB, }; static const struct platform_features ivb_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_SNB, }; static const struct platform_features ivx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_SNB, }; static const struct platform_features hsw_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features hsx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features hswl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features hswg_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features bdw_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features bdwg_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features bdx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features skl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features cnl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_HSW, }; static const struct platform_features skx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_SKX, }; static const struct platform_features icx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_ICX, }; static const struct platform_features spr_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_SKX, }; static const struct platform_features slv_features = { .bclk_freq = BCLK_SLV, + .cst_limit = CST_LIMIT_SLV, }; static const struct platform_features slvd_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_SLV, + .cst_limit = CST_LIMIT_SLV, }; static const struct platform_features amt_features = { .bclk_freq = BCLK_133MHZ, + .cst_limit = CST_LIMIT_AMT, }; static const struct platform_features gmt_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features gmtd_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features gmtp_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features tmtd_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features knl_features = { .has_msr_misc_pwr_mgmt = 1, .bclk_freq = BCLK_100MHZ, + .cst_limit = CST_LIMIT_KNL, }; static const struct platform_features default_features = { @@ -2704,6 +2745,50 @@ int icx_pkg_cstate_limits[16] = PCLRSV, PCLRSV }; +void probe_cst_limit(void) +{ + unsigned long long msr; + int *pkg_cstate_limits; + + if (!do_nhm_platform_info) + return; + + switch (platform->cst_limit) { + case CST_LIMIT_NHM: + pkg_cstate_limits = nhm_pkg_cstate_limits; + break; + case CST_LIMIT_SNB: + pkg_cstate_limits = snb_pkg_cstate_limits; + break; + case CST_LIMIT_HSW: + pkg_cstate_limits = hsw_pkg_cstate_limits; + break; + case CST_LIMIT_SKX: + pkg_cstate_limits = skx_pkg_cstate_limits; + break; + case CST_LIMIT_ICX: + pkg_cstate_limits = icx_pkg_cstate_limits; + break; + case CST_LIMIT_SLV: + pkg_cstate_limits = slv_pkg_cstate_limits; + break; + case CST_LIMIT_AMT: + pkg_cstate_limits = amt_pkg_cstate_limits; + break; + case CST_LIMIT_KNL: + pkg_cstate_limits = phi_pkg_cstate_limits; + break; + case CST_LIMIT_GMT: + pkg_cstate_limits = glm_pkg_cstate_limits; + break; + default: + return; + } + + get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr); + pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; +} + static void calculate_tsc_tweak() { tsc_tweak = base_hz / tsc_hz; @@ -4006,15 +4091,9 @@ void probe_bclk(void) * MSR_PKG_C6_RESIDENCY 0x000003f9 * MSR_CORE_C3_RESIDENCY 0x000003fc * MSR_CORE_C6_RESIDENCY 0x000003fd - * - * Side effect: - * sets global pkg_cstate_limit to decode MSR_PKG_CST_CONFIG_CONTROL */ int probe_nhm_msrs(unsigned int family, unsigned int model) { - unsigned long long msr; - int *pkg_cstate_limits; - if (!genuine_intel) return 0; @@ -4024,14 +4103,10 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) switch (model) { case INTEL_FAM6_NEHALEM: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */ case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ - pkg_cstate_limits = nhm_pkg_cstate_limits; - break; case INTEL_FAM6_SANDYBRIDGE: /* SNB */ case INTEL_FAM6_SANDYBRIDGE_X: /* SNB Xeon */ case INTEL_FAM6_IVYBRIDGE: /* IVB */ case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ - pkg_cstate_limits = snb_pkg_cstate_limits; - break; case INTEL_FAM6_HASWELL: /* HSW */ case INTEL_FAM6_HASWELL_G: /* HSW */ case INTEL_FAM6_HASWELL_X: /* HSX */ @@ -4041,38 +4116,22 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) case INTEL_FAM6_BROADWELL_X: /* BDX */ case INTEL_FAM6_SKYLAKE_L: /* SKL */ case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - pkg_cstate_limits = hsw_pkg_cstate_limits; - break; case INTEL_FAM6_SKYLAKE_X: /* SKX */ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ - pkg_cstate_limits = skx_pkg_cstate_limits; - break; case INTEL_FAM6_ICELAKE_X: /* ICX */ - pkg_cstate_limits = icx_pkg_cstate_limits; - break; case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ - /* FALLTHRU */ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ - pkg_cstate_limits = slv_pkg_cstate_limits; - break; case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ - pkg_cstate_limits = amt_pkg_cstate_limits; - break; case INTEL_FAM6_XEON_PHI_KNL: /* PHI */ - pkg_cstate_limits = phi_pkg_cstate_limits; - break; case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ case INTEL_FAM6_ATOM_TREMONT: /* EHL */ case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */ - pkg_cstate_limits = glm_pkg_cstate_limits; break; default: return 0; } - get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr); - pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; return 1; } @@ -5964,6 +6023,7 @@ void process_cpuid() BIC_PRESENT(BIC_IRQ); BIC_PRESENT(BIC_TSC_MHz); + probe_cst_limit(); if (probe_nhm_msrs(family, model)) { do_nhm_platform_info = 1; BIC_PRESENT(BIC_CPU_c1); -- cgit v1.2.3 From fcfa1ce074ab76272639961d4d7900b91657a8d5 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 25 Aug 2023 16:52:23 +0800 Subject: tools/power/turbostat: Abstract Nehalem MSRs support MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, and the TRL MSRs are always available for platforms since Nehalem. Support for these msrs can be described altogether. Abstract the support for these MSRs. Delete probe_nhm_msrs() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 101 ++++++++++++---------------------- 1 file changed, 34 insertions(+), 67 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index bcad9332a3b2..bc221e800aec 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -237,7 +237,6 @@ unsigned int authentic_amd; unsigned int hygon_genuine; unsigned int max_level, max_extended_level; unsigned int has_invariant_tsc; -unsigned int do_nhm_platform_info; unsigned int aperf_mperf_multiplier = 1; double bclk; double base_hz; @@ -286,6 +285,7 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr); struct platform_features { bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */ bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */ + bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, TRL MSRs */ int bclk_freq; /* CPU base clock */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ }; @@ -342,12 +342,14 @@ enum package_cstate_limit { static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, .cst_limit = CST_LIMIT_NHM, }; static const struct platform_features nhx_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, .cst_limit = CST_LIMIT_NHM, }; @@ -355,6 +357,7 @@ static const struct platform_features nhx_features = { static const struct platform_features snb_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, }; @@ -362,6 +365,7 @@ static const struct platform_features snb_features = { static const struct platform_features snx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, }; @@ -369,6 +373,7 @@ static const struct platform_features snx_features = { static const struct platform_features ivb_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, }; @@ -376,6 +381,7 @@ static const struct platform_features ivb_features = { static const struct platform_features ivx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, }; @@ -383,6 +389,7 @@ static const struct platform_features ivx_features = { static const struct platform_features hsw_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -390,6 +397,7 @@ static const struct platform_features hsw_features = { static const struct platform_features hsx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -397,6 +405,7 @@ static const struct platform_features hsx_features = { static const struct platform_features hswl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -404,6 +413,7 @@ static const struct platform_features hswl_features = { static const struct platform_features hswg_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -411,6 +421,7 @@ static const struct platform_features hswg_features = { static const struct platform_features bdw_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -418,6 +429,7 @@ static const struct platform_features bdw_features = { static const struct platform_features bdwg_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -425,6 +437,7 @@ static const struct platform_features bdwg_features = { static const struct platform_features bdx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -432,6 +445,7 @@ static const struct platform_features bdx_features = { static const struct platform_features skl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -439,6 +453,7 @@ static const struct platform_features skl_features = { static const struct platform_features cnl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, }; @@ -446,6 +461,7 @@ static const struct platform_features cnl_features = { static const struct platform_features skx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SKX, }; @@ -453,6 +469,7 @@ static const struct platform_features skx_features = { static const struct platform_features icx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_ICX, }; @@ -460,58 +477,68 @@ static const struct platform_features icx_features = { static const struct platform_features spr_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SKX, }; static const struct platform_features slv_features = { + .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, .cst_limit = CST_LIMIT_SLV, }; static const struct platform_features slvd_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, .cst_limit = CST_LIMIT_SLV, }; static const struct platform_features amt_features = { + .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, .cst_limit = CST_LIMIT_AMT, }; static const struct platform_features gmt_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features gmtd_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features gmtp_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features tmtd_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, }; static const struct platform_features knl_features = { .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_KNL, }; @@ -2750,7 +2777,7 @@ void probe_cst_limit(void) unsigned long long msr; int *pkg_cstate_limits; - if (!do_nhm_platform_info) + if (!platform->has_nhm_msrs) return; switch (platform->cst_limit) { @@ -4058,7 +4085,7 @@ void probe_bclk(void) unsigned long long msr; unsigned int base_ratio; - if (!do_nhm_platform_info) + if (!platform->has_nhm_msrs) return; if (platform->bclk_freq == BCLK_100MHZ) @@ -4077,65 +4104,6 @@ void probe_bclk(void) has_base_hz = 1; } -/* - * NHM adds support for additional MSRs: - * - * MSR_SMI_COUNT 0x00000034 - * - * MSR_PLATFORM_INFO 0x000000ce - * MSR_PKG_CST_CONFIG_CONTROL 0x000000e2 - * - * MSR_MISC_PWR_MGMT 0x000001aa - * - * MSR_PKG_C3_RESIDENCY 0x000003f8 - * MSR_PKG_C6_RESIDENCY 0x000003f9 - * MSR_CORE_C3_RESIDENCY 0x000003fc - * MSR_CORE_C6_RESIDENCY 0x000003fd - */ -int probe_nhm_msrs(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_NEHALEM: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */ - case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ - case INTEL_FAM6_SANDYBRIDGE: /* SNB */ - case INTEL_FAM6_SANDYBRIDGE_X: /* SNB Xeon */ - case INTEL_FAM6_IVYBRIDGE: /* IVB */ - case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ - case INTEL_FAM6_HASWELL: /* HSW */ - case INTEL_FAM6_HASWELL_G: /* HSW */ - case INTEL_FAM6_HASWELL_X: /* HSX */ - case INTEL_FAM6_HASWELL_L: /* HSW */ - case INTEL_FAM6_BROADWELL: /* BDW */ - case INTEL_FAM6_BROADWELL_G: /* BDW */ - case INTEL_FAM6_BROADWELL_X: /* BDX */ - case INTEL_FAM6_SKYLAKE_L: /* SKL */ - case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - case INTEL_FAM6_SKYLAKE_X: /* SKX */ - case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ - case INTEL_FAM6_ICELAKE_X: /* ICX */ - case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ - case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ - case INTEL_FAM6_ATOM_AIRMONT: /* AMT */ - case INTEL_FAM6_XEON_PHI_KNL: /* PHI */ - case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GOLDMONT_PLUS: - case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ - case INTEL_FAM6_ATOM_TREMONT: /* EHL */ - case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */ - break; - default: - return 0; - } - - return 1; -} - /* * SLV client has support for unique MSRs: * @@ -4461,7 +4429,7 @@ static void dump_turbo_ratio_info(unsigned int family, unsigned int model) static void dump_cstate_pstate_config_info(unsigned int family, unsigned int model) { - if (!do_nhm_platform_info) + if (!platform->has_nhm_msrs) return; dump_nhm_platform_info(); @@ -5606,7 +5574,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk } /* Temperature Target MSR is Nehalem and newer only */ - if (!do_nhm_platform_info) + if (!platform->has_nhm_msrs) goto guess; if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr)) @@ -5697,7 +5665,7 @@ void decode_misc_pwr_mgmt_msr(void) { unsigned long long msr; - if (!do_nhm_platform_info) + if (!platform->has_nhm_msrs) return; if (!platform->has_msr_misc_pwr_mgmt) @@ -6024,8 +5992,7 @@ void process_cpuid() BIC_PRESENT(BIC_TSC_MHz); probe_cst_limit(); - if (probe_nhm_msrs(family, model)) { - do_nhm_platform_info = 1; + if (platform->has_nhm_msrs) { BIC_PRESENT(BIC_CPU_c1); BIC_PRESENT(BIC_CPU_c3); BIC_PRESENT(BIC_CPU_c6); -- cgit v1.2.3 From c2c25e85df316a624e4a8ee85d65ea29265f486d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 27 Mar 2023 14:57:06 +0800 Subject: tools/power/turbostat: Remove a redundant check Platforms with has_msr_misc_pwr_mgmt set is a subset of platforms with has_nhm_msrs set. Thus remove the redudant check for platform->has_nhm_msrs. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index bc221e800aec..4eb10491f714 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5665,9 +5665,6 @@ void decode_misc_pwr_mgmt_msr(void) { unsigned long long msr; - if (!platform->has_nhm_msrs) - return; - if (!platform->has_msr_misc_pwr_mgmt) return; -- cgit v1.2.3 From 8b7199c0855e3b22532a21aaaed78e699431e4e5 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 27 Mar 2023 14:58:35 +0800 Subject: tools/power/turbostat: Rename some functions Rename dump_nhm_platform_info() and dump_nhm_cst_cfg() to dump_platform_info() and dump_cst_cfg() because these MSRs' behavior is consistent when they're available. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 4eb10491f714..654ae1ce130c 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2823,7 +2823,7 @@ static void calculate_tsc_tweak() void prewake_cstate_probe(unsigned int family, unsigned int model); -static void dump_nhm_platform_info(void) +static void dump_platform_info(void) { unsigned long long msr; unsigned int ratio; @@ -3059,7 +3059,7 @@ static void dump_knl_turbo_ratio_limits(void) ratio[i], bclk, ratio[i] * bclk, cores[i]); } -static void dump_nhm_cst_cfg(void) +static void dump_cst_cfg(void) { unsigned long long msr; @@ -4432,9 +4432,9 @@ static void dump_cstate_pstate_config_info(unsigned int family, unsigned int mod if (!platform->has_nhm_msrs) return; - dump_nhm_platform_info(); + dump_platform_info(); dump_turbo_ratio_info(family, model); - dump_nhm_cst_cfg(); + dump_cst_cfg(); } static int read_sysfs_int(char *path) -- cgit v1.2.3 From 10d85d85ab4f3ae7faca4450ce7b0a166fd396f0 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 8 Sep 2023 23:16:00 +0800 Subject: tools/power/turbostat: Abstract Turbo Ratio Limit MSRs support Abstract the support for MSR_TURBO_RATIO_LIMIT, MSR_TRUBO_RATIO_LIMIT1, MSR_TURBO_RATIO_LIMIT2, MSR_SECONDARY_TURBO_RATIO_LIMIT, MSR_ATOM_CORE_RATIOS and MSR_ATOM_CORE_TURBO_RATIOS. Delete has_turbo_ratio_group_limits(), has_turbo_ratio_limit(), has_atom_turbo_ratio_limit(), has_ivt_turbo_ratio_limit(), has_hsw_turbo_ratio_limit(), has_knl_turbo_ratio_limit() and has_glm_turbo_ratio_limit() CPU model checks. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 171 +++++++++------------------------- 1 file changed, 46 insertions(+), 125 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 654ae1ce130c..b6c53ec740d3 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -288,6 +288,7 @@ struct platform_features { bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, TRL MSRs */ int bclk_freq; /* CPU base clock */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ + int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ }; struct platform_data { @@ -340,11 +341,22 @@ enum package_cstate_limit { CST_LIMIT_GMT, }; +/* For Turbo Ratio Limit MSRs */ +enum turbo_ratio_limit_msrs { + TRL_BASE = BIT(0), + TRL_LIMIT1 = BIT(1), + TRL_LIMIT2 = BIT(2), + TRL_ATOM = BIT(3), + TRL_KNL = BIT(4), + TRL_CORECOUNT = BIT(5), +}; + static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, .cst_limit = CST_LIMIT_NHM, + .trl_msrs = TRL_BASE, }; static const struct platform_features nhx_features = { @@ -360,6 +372,7 @@ static const struct platform_features snb_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, + .trl_msrs = TRL_BASE, }; static const struct platform_features snx_features = { @@ -368,6 +381,7 @@ static const struct platform_features snx_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, + .trl_msrs = TRL_BASE, }; static const struct platform_features ivb_features = { @@ -376,6 +390,7 @@ static const struct platform_features ivb_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, + .trl_msrs = TRL_BASE, }; static const struct platform_features ivx_features = { @@ -384,6 +399,7 @@ static const struct platform_features ivx_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, + .trl_msrs = TRL_BASE | TRL_LIMIT1, }; static const struct platform_features hsw_features = { @@ -392,6 +408,7 @@ static const struct platform_features hsw_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE, }; static const struct platform_features hsx_features = { @@ -400,6 +417,7 @@ static const struct platform_features hsx_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, }; static const struct platform_features hswl_features = { @@ -408,6 +426,7 @@ static const struct platform_features hswl_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE, }; static const struct platform_features hswg_features = { @@ -416,6 +435,7 @@ static const struct platform_features hswg_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE, }; static const struct platform_features bdw_features = { @@ -424,6 +444,7 @@ static const struct platform_features bdw_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE, }; static const struct platform_features bdwg_features = { @@ -432,6 +453,7 @@ static const struct platform_features bdwg_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE, }; static const struct platform_features bdx_features = { @@ -440,6 +462,7 @@ static const struct platform_features bdx_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE, }; static const struct platform_features skl_features = { @@ -448,6 +471,7 @@ static const struct platform_features skl_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE, }; static const struct platform_features cnl_features = { @@ -456,6 +480,7 @@ static const struct platform_features cnl_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .trl_msrs = TRL_BASE, }; static const struct platform_features skx_features = { @@ -464,6 +489,7 @@ static const struct platform_features skx_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SKX, + .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; static const struct platform_features icx_features = { @@ -472,6 +498,7 @@ static const struct platform_features icx_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_ICX, + .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; static const struct platform_features spr_features = { @@ -480,12 +507,14 @@ static const struct platform_features spr_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SKX, + .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; static const struct platform_features slv_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, .cst_limit = CST_LIMIT_SLV, + .trl_msrs = TRL_ATOM, }; static const struct platform_features slvd_features = { @@ -493,12 +522,14 @@ static const struct platform_features slvd_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, .cst_limit = CST_LIMIT_SLV, + .trl_msrs = TRL_BASE, }; static const struct platform_features amt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, .cst_limit = CST_LIMIT_AMT, + .trl_msrs = TRL_BASE, }; static const struct platform_features gmt_features = { @@ -506,6 +537,7 @@ static const struct platform_features gmt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, + .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; static const struct platform_features gmtd_features = { @@ -513,6 +545,7 @@ static const struct platform_features gmtd_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, + .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; static const struct platform_features gmtp_features = { @@ -520,6 +553,7 @@ static const struct platform_features gmtp_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, + .trl_msrs = TRL_BASE, }; static const struct platform_features tmt_features = { @@ -527,6 +561,7 @@ static const struct platform_features tmt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, + .trl_msrs = TRL_BASE, }; static const struct platform_features tmtd_features = { @@ -534,6 +569,7 @@ static const struct platform_features tmtd_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, + .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; static const struct platform_features knl_features = { @@ -541,6 +577,7 @@ static const struct platform_features knl_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_KNL, + .trl_msrs = TRL_KNL, }; static const struct platform_features default_features = { @@ -2911,29 +2948,7 @@ static void dump_ivt_turbo_ratio_limits(void) return; } -int has_turbo_ratio_group_limits(int family, int model) -{ - - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_ATOM_GOLDMONT: - case INTEL_FAM6_SKYLAKE_X: - case INTEL_FAM6_ICELAKE_X: - case INTEL_FAM6_SAPPHIRERAPIDS_X: - case INTEL_FAM6_ATOM_GOLDMONT_D: - case INTEL_FAM6_ATOM_TREMONT_D: - return 1; - default: - return 0; - } -} - -static void dump_turbo_ratio_limits(int trl_msr_offset, int family, int model) +static void dump_turbo_ratio_limits(int trl_msr_offset) { unsigned long long msr, core_counts; int shift; @@ -2942,7 +2957,7 @@ static void dump_turbo_ratio_limits(int trl_msr_offset, int family, int model) fprintf(outf, "cpu%d: MSR_%sTURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY_" : "", msr); - if (has_turbo_ratio_group_limits(family, model)) { + if (platform->trl_msrs & TRL_CORECOUNT) { get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts); fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, core_counts); } else { @@ -4236,100 +4251,6 @@ int is_jvl(unsigned int family, unsigned int model) return 0; } -int has_turbo_ratio_limit(unsigned int family, unsigned int model) -{ - if (has_slv_msrs(family, model)) - return 0; - - if (family != 6) - return 0; - - switch (model) { - /* Nehalem compatible, but do not include turbo-ratio limit support */ - case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */ - case INTEL_FAM6_XEON_PHI_KNL: /* PHI - Knights Landing (different MSR definition) */ - return 0; - default: - return 1; - } -} - -int has_atom_turbo_ratio_limit(unsigned int family, unsigned int model) -{ - if (has_slv_msrs(family, model)) - return 1; - - return 0; -} - -int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ - case INTEL_FAM6_HASWELL_X: /* HSW Xeon */ - return 1; - default: - return 0; - } -} - -int has_hsw_turbo_ratio_limit(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_HASWELL_X: /* HSW Xeon */ - return 1; - default: - return 0; - } -} - -int has_knl_turbo_ratio_limit(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */ - return 1; - default: - return 0; - } -} - -int has_glm_turbo_ratio_limit(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_ATOM_GOLDMONT: - case INTEL_FAM6_SKYLAKE_X: - case INTEL_FAM6_ICELAKE_X: - case INTEL_FAM6_SAPPHIRERAPIDS_X: - return 1; - default: - return 0; - } -} - int has_config_tdp(unsigned int family, unsigned int model) { if (!genuine_intel) @@ -4404,23 +4325,23 @@ static void dump_turbo_ratio_info(unsigned int family, unsigned int model) if (!has_turbo) return; - if (has_hsw_turbo_ratio_limit(family, model)) + if (platform->trl_msrs & TRL_LIMIT2) dump_hsw_turbo_ratio_limits(); - if (has_ivt_turbo_ratio_limit(family, model)) + if (platform->trl_msrs & TRL_LIMIT1) dump_ivt_turbo_ratio_limits(); - if (has_turbo_ratio_limit(family, model)) { - dump_turbo_ratio_limits(MSR_TURBO_RATIO_LIMIT, family, model); + if (platform->trl_msrs & TRL_BASE) { + dump_turbo_ratio_limits(MSR_TURBO_RATIO_LIMIT); if (is_hybrid) - dump_turbo_ratio_limits(MSR_SECONDARY_TURBO_RATIO_LIMIT, family, model); + dump_turbo_ratio_limits(MSR_SECONDARY_TURBO_RATIO_LIMIT); } - if (has_atom_turbo_ratio_limit(family, model)) + if (platform->trl_msrs & TRL_ATOM) dump_atom_turbo_ratio_limits(); - if (has_knl_turbo_ratio_limit(family, model)) + if (platform->trl_msrs & TRL_KNL) dump_knl_turbo_ratio_limits(); if (has_config_tdp(family, model)) -- cgit v1.2.3 From a3943deaf98f713c819dd7e67af734d4ed4da030 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 30 Jul 2023 13:54:25 +0800 Subject: tools/power/turbostat: Rename some TRL functions Rename dump_hsw_turbo_ratio_limits() and dump_ivt_turbo_ratio_limits() to dump_turbo_ratio_limit2() and dump_turbo_ratio_limit1() because they dump MSR_TURBO_RATIO_LIMIT1/LIMIT2, and the MSRs' behavior is consistent when they are available. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index b6c53ec740d3..abcc055ea0e1 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2886,7 +2886,7 @@ static void dump_platform_info(void) return; } -static void dump_hsw_turbo_ratio_limits(void) +static void dump_turbo_ratio_limit2(void) { unsigned long long msr; unsigned int ratio; @@ -2905,7 +2905,7 @@ static void dump_hsw_turbo_ratio_limits(void) return; } -static void dump_ivt_turbo_ratio_limits(void) +static void dump_turbo_ratio_limit1(void) { unsigned long long msr; unsigned int ratio; @@ -4326,10 +4326,10 @@ static void dump_turbo_ratio_info(unsigned int family, unsigned int model) return; if (platform->trl_msrs & TRL_LIMIT2) - dump_hsw_turbo_ratio_limits(); + dump_turbo_ratio_limit2(); if (platform->trl_msrs & TRL_LIMIT1) - dump_ivt_turbo_ratio_limits(); + dump_turbo_ratio_limit1(); if (platform->trl_msrs & TRL_BASE) { dump_turbo_ratio_limits(MSR_TURBO_RATIO_LIMIT); -- cgit v1.2.3 From a61c9cb478c0bf31a50d1829834e822e92876c95 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 14:19:46 +0800 Subject: tools/power/turbostat: Abstract Config TDP MSRs support Abstract the support for MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL and MSR_TURBO_ACTIVATION_RATIO. Delete has_config_tdp() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 54 +++++++++++++---------------------- 1 file changed, 20 insertions(+), 34 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index abcc055ea0e1..bb9d8c2605c8 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -286,6 +286,7 @@ struct platform_features { bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */ bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */ bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, TRL MSRs */ + bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */ int bclk_freq; /* CPU base clock */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ @@ -388,6 +389,7 @@ static const struct platform_features ivb_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, @@ -406,6 +408,7 @@ static const struct platform_features hsw_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, @@ -415,6 +418,7 @@ static const struct platform_features hsx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, @@ -424,6 +428,7 @@ static const struct platform_features hswl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, @@ -433,6 +438,7 @@ static const struct platform_features hswg_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, @@ -442,6 +448,7 @@ static const struct platform_features bdw_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, @@ -451,6 +458,7 @@ static const struct platform_features bdwg_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, @@ -460,6 +468,7 @@ static const struct platform_features bdx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, @@ -469,6 +478,7 @@ static const struct platform_features skl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, @@ -478,6 +488,7 @@ static const struct platform_features cnl_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, @@ -487,6 +498,7 @@ static const struct platform_features skx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SKX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, @@ -496,6 +508,7 @@ static const struct platform_features icx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_ICX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, @@ -505,6 +518,7 @@ static const struct platform_features spr_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SKX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, @@ -575,6 +589,7 @@ static const struct platform_features tmtd_features = { static const struct platform_features knl_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, + .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_KNL, .trl_msrs = TRL_KNL, @@ -4251,35 +4266,6 @@ int is_jvl(unsigned int family, unsigned int model) return 0; } -int has_config_tdp(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_IVYBRIDGE: /* IVB */ - case INTEL_FAM6_HASWELL: /* HSW */ - case INTEL_FAM6_HASWELL_X: /* HSX */ - case INTEL_FAM6_HASWELL_L: /* HSW */ - case INTEL_FAM6_HASWELL_G: /* HSW */ - case INTEL_FAM6_BROADWELL: /* BDW */ - case INTEL_FAM6_BROADWELL_G: /* BDW */ - case INTEL_FAM6_BROADWELL_X: /* BDX */ - case INTEL_FAM6_SKYLAKE_L: /* SKL */ - case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - case INTEL_FAM6_SKYLAKE_X: /* SKX */ - case INTEL_FAM6_ICELAKE_X: /* ICX */ - case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ - case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */ - return 1; - default: - return 0; - } -} - /* * tcc_offset_bits: * 0: Tcc Offset not supported (Default) @@ -4320,7 +4306,7 @@ static void remove_underbar(char *s) *to = 0; } -static void dump_turbo_ratio_info(unsigned int family, unsigned int model) +static void dump_turbo_ratio_info(void) { if (!has_turbo) return; @@ -4344,17 +4330,17 @@ static void dump_turbo_ratio_info(unsigned int family, unsigned int model) if (platform->trl_msrs & TRL_KNL) dump_knl_turbo_ratio_limits(); - if (has_config_tdp(family, model)) + if (platform->has_config_tdp) dump_config_tdp(); } -static void dump_cstate_pstate_config_info(unsigned int family, unsigned int model) +static void dump_cstate_pstate_config_info(void) { if (!platform->has_nhm_msrs) return; dump_platform_info(); - dump_turbo_ratio_info(family, model); + dump_turbo_ratio_info(); dump_cst_cfg(); } @@ -6000,7 +5986,7 @@ void process_cpuid() check_tcc_offset(model); if (!quiet) - dump_cstate_pstate_config_info(family, model); + dump_cstate_pstate_config_info(); intel_uncore_frequency_probe(); if (!quiet) -- cgit v1.2.3 From d8e1623baa0b49aa90cf5801cfaac9e3d3aa1e19 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 25 Aug 2023 23:04:44 +0800 Subject: tools/power/turbostat: Abstract TCC Offset bits support Abstract the support for different TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET. Delete check_tcc_offset() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 53 ++++++++--------------------------- 1 file changed, 12 insertions(+), 41 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index bb9d8c2605c8..c39beb4078da 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -256,7 +256,6 @@ unsigned int gfx_cur_mhz; unsigned int gfx_act_mhz; unsigned int tj_max; unsigned int tj_max_override; -int tcc_offset_bits; double rapl_power_units, rapl_time_units; double rapl_dram_energy_units, rapl_energy_units; double rapl_joule_counter_range; @@ -290,6 +289,7 @@ struct platform_features { int bclk_freq; /* CPU base clock */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ + int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ }; struct platform_data { @@ -482,6 +482,7 @@ static const struct platform_features skl_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, + .tcc_offset_bits = 6, }; static const struct platform_features cnl_features = { @@ -492,6 +493,7 @@ static const struct platform_features cnl_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, + .tcc_offset_bits = 6, }; static const struct platform_features skx_features = { @@ -4266,33 +4268,6 @@ int is_jvl(unsigned int family, unsigned int model) return 0; } -/* - * tcc_offset_bits: - * 0: Tcc Offset not supported (Default) - * 6: Bit 29:24 of MSR_PLATFORM_INFO - * 4: Bit 27:24 of MSR_PLATFORM_INFO - */ -void check_tcc_offset(int model) -{ - unsigned long long msr; - - if (!genuine_intel) - return; - - switch (model) { - case INTEL_FAM6_SKYLAKE_L: - case INTEL_FAM6_CANNONLAKE_L: - if (!get_msr(base_cpu, MSR_PLATFORM_INFO, &msr)) { - msr = (msr >> 30) & 1; - if (msr) - tcc_offset_bits = 6; - } - return; - default: - return; - } -} - static void remove_underbar(char *s) { char *to = s; @@ -5490,20 +5465,18 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk tcc_default = (msr >> 16) & 0xFF; if (!quiet) { - switch (tcc_offset_bits) { - case 4: - tcc_offset = (msr >> 24) & 0xF; - fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n", - cpu, msr, tcc_default - tcc_offset, tcc_default, tcc_offset); - break; - case 6: - tcc_offset = (msr >> 24) & 0x3F; + int bits = platform->tcc_offset_bits; + unsigned long long enabled = 0; + + if (bits && !get_msr(base_cpu, MSR_PLATFORM_INFO, &enabled)) + enabled = (enabled >> 30) & 1; + + if (bits && enabled) { + tcc_offset = (msr >> 24) & GENMASK(bits - 1, 0); fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n", cpu, msr, tcc_default - tcc_offset, tcc_default, tcc_offset); - break; - default: + } else { fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", cpu, msr, tcc_default); - break; } } @@ -5983,8 +5956,6 @@ void process_cpuid() automatic_cstate_conversion_probe(family, model); prewake_cstate_probe(family, model); - check_tcc_offset(model); - if (!quiet) dump_cstate_pstate_config_info(); intel_uncore_frequency_probe(); -- cgit v1.2.3 From 0c057cf7a0e163bf9631b83c002b3a55691674c7 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 30 Jul 2023 14:25:17 +0800 Subject: tools/power/turbostat: Abstract Perf Limit Reasons MSRs support Abstract the support for MSR_CORE/GFX/RING_PERF_LIMIT_REASONS MSRs. Delete perf_limit_reasons_probe() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 44 ++++++++++++----------------------- 1 file changed, 15 insertions(+), 29 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index c39beb4078da..1207845340ad 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -259,11 +259,8 @@ unsigned int tj_max_override; double rapl_power_units, rapl_time_units; double rapl_dram_energy_units, rapl_energy_units; double rapl_joule_counter_range; -unsigned int do_core_perf_limit_reasons; unsigned int has_automatic_cstate_conversion; unsigned int dis_cstate_prewake; -unsigned int do_gfx_perf_limit_reasons; -unsigned int do_ring_perf_limit_reasons; unsigned int crystal_hz; unsigned long long tsc_hz; int base_cpu; @@ -289,6 +286,7 @@ struct platform_features { int bclk_freq; /* CPU base clock */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ + int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ }; @@ -352,6 +350,13 @@ enum turbo_ratio_limit_msrs { TRL_CORECOUNT = BIT(5), }; +/* For Perf Limit Reason MSRs */ +enum perf_limit_reason_msrs { + PLR_CORE = BIT(0), + PLR_GFX = BIT(1), + PLR_RING = BIT(2), +}; + static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, @@ -412,6 +417,7 @@ static const struct platform_features hsw_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, + .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, }; static const struct platform_features hsx_features = { @@ -422,6 +428,7 @@ static const struct platform_features hsx_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, + .plr_msrs = PLR_CORE | PLR_RING, }; static const struct platform_features hswl_features = { @@ -432,6 +439,7 @@ static const struct platform_features hswl_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, + .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, }; static const struct platform_features hswg_features = { @@ -442,6 +450,7 @@ static const struct platform_features hswg_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, + .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, }; static const struct platform_features bdw_features = { @@ -4657,7 +4666,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data return -1; } - if (do_core_perf_limit_reasons) { + if (platform->plr_msrs & PLR_CORE) { get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr); fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)", @@ -4690,7 +4699,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data (msr & 1 << 17) ? "ThermStatus, " : "", (msr & 1 << 16) ? "PROCHOT, " : ""); } - if (do_gfx_perf_limit_reasons) { + if (platform->plr_msrs & PLR_GFX) { get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr); fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)", @@ -4710,7 +4719,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data (msr & 1 << 25) ? "GFXPwr, " : "", (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : ""); } - if (do_ring_perf_limit_reasons) { + if (platform->plr_msrs & PLR_RING) { get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr); fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); fprintf(outf, " (Active: %s%s%s%s%s%s)", @@ -5002,28 +5011,6 @@ void rapl_probe(unsigned int family, unsigned int model) rapl_probe_amd(family, model); } -void perf_limit_reasons_probe(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return; - - if (family != 6) - return; - - switch (model) { - case INTEL_FAM6_HASWELL: /* HSW */ - case INTEL_FAM6_HASWELL_L: /* HSW */ - case INTEL_FAM6_HASWELL_G: /* HSW */ - do_gfx_perf_limit_reasons = 1; - /* FALLTHRU */ - case INTEL_FAM6_HASWELL_X: /* HSX */ - do_core_perf_limit_reasons = 1; - do_ring_perf_limit_reasons = 1; - default: - return; - } -} - void automatic_cstate_conversion_probe(unsigned int family, unsigned int model) { if (family != 6) @@ -5952,7 +5939,6 @@ void process_cpuid() decode_c6_demotion_policy_msr(); rapl_probe(family, model); - perf_limit_reasons_probe(family, model); automatic_cstate_conversion_probe(family, model); prewake_cstate_probe(family, model); -- cgit v1.2.3 From d90120bf9f111bec8ba0b8ef86c46ccbcd9df188 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 22 Apr 2023 11:29:18 +0800 Subject: tools/power/turbostat: Abstract Automatic Cstate Conversion support Abstract the support for AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL. Delete automatic_cstate_conversion_probe() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 1207845340ad..a235cbf7b581 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -259,7 +259,6 @@ unsigned int tj_max_override; double rapl_power_units, rapl_time_units; double rapl_dram_energy_units, rapl_energy_units; double rapl_joule_counter_range; -unsigned int has_automatic_cstate_conversion; unsigned int dis_cstate_prewake; unsigned int crystal_hz; unsigned long long tsc_hz; @@ -285,6 +284,7 @@ struct platform_features { bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */ int bclk_freq; /* CPU base clock */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ + bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ @@ -480,6 +480,7 @@ static const struct platform_features bdx_features = { .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, + .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, }; @@ -512,6 +513,7 @@ static const struct platform_features skx_features = { .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SKX, + .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; @@ -3116,7 +3118,7 @@ static void dump_cst_cfg(void) (msr & (1 << 15)) ? "" : "UN", (unsigned int)msr & 0xF, pkg_cstate_limit_strings[pkg_cstate_limit]); #define AUTOMATIC_CSTATE_CONVERSION (1UL << 16) - if (has_automatic_cstate_conversion) { + if (platform->has_cst_auto_convension) { fprintf(outf, ", automatic c-state conversion=%s", (msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off"); } @@ -5011,18 +5013,6 @@ void rapl_probe(unsigned int family, unsigned int model) rapl_probe_amd(family, model); } -void automatic_cstate_conversion_probe(unsigned int family, unsigned int model) -{ - if (family != 6) - return; - - switch (model) { - case INTEL_FAM6_BROADWELL_X: - case INTEL_FAM6_SKYLAKE_X: - has_automatic_cstate_conversion = 1; - } -} - void prewake_cstate_probe(unsigned int family, unsigned int model) { if (is_icx(family, model) || is_spr(family, model)) @@ -5939,7 +5929,6 @@ void process_cpuid() decode_c6_demotion_policy_msr(); rapl_probe(family, model); - automatic_cstate_conversion_probe(family, model); prewake_cstate_probe(family, model); if (!quiet) -- cgit v1.2.3 From a5d1ab93a0993616efbf61378e491d6673f4684d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 22 Apr 2023 11:39:49 +0800 Subject: tools/power/turbostat: Abstract hardcoded Crystal Clock frequency Abstract the support for hardcoded Crystal Clock frequency, which is used when crystal clock is not available from CPUID.15. Delete CPU model checks in process_cpuid(). Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a235cbf7b581..c76baa10f4eb 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -283,6 +283,7 @@ struct platform_features { bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, TRL MSRs */ bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */ int bclk_freq; /* CPU base clock */ + int crystal_freq; /* Crystal clock to use when not available from CPUID.15 */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ @@ -490,6 +491,7 @@ static const struct platform_features skl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .crystal_freq = 24000000, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -563,6 +565,7 @@ static const struct platform_features gmt_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, + .crystal_freq = 19200000, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; @@ -571,6 +574,7 @@ static const struct platform_features gmtd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, + .crystal_freq = 25000000, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, }; @@ -579,6 +583,7 @@ static const struct platform_features gmtp_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, + .crystal_freq = 19200000, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, }; @@ -5796,26 +5801,12 @@ void process_cpuid() __cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx); if (ebx_tsc != 0) { - if (!quiet && (ebx != 0)) fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n", eax_crystal, ebx_tsc, crystal_hz); if (crystal_hz == 0) - switch (model) { - case INTEL_FAM6_SKYLAKE_L: /* SKL */ - crystal_hz = 24000000; /* 24.0 MHz */ - break; - case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ - crystal_hz = 25000000; /* 25.0 MHz */ - break; - case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GOLDMONT_PLUS: - crystal_hz = 19200000; /* 19.2 MHz */ - break; - default: - crystal_hz = 0; - } + crystal_hz = platform->crystal_freq; if (crystal_hz) { tsc_hz = (unsigned long long)crystal_hz *ebx_tsc / eax_crystal; -- cgit v1.2.3 From b9cd66833d3a651cea10666674e9abcf2182e8ad Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 26 Aug 2023 14:38:38 +0800 Subject: tools/power/turbostat: Redefine RAPL macros Redefine RAPL macros to make the code more readable. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 102 +++++++++++++++------------------- 1 file changed, 45 insertions(+), 57 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index c76baa10f4eb..4829e8289feb 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -358,6 +358,40 @@ enum perf_limit_reason_msrs { PLR_RING = BIT(2), }; +/* For RAPL MSRs */ +enum rapl_msrs { + RAPL_PKG_POWER_LIMIT = BIT(0), /* 0x610 MSR_PKG_POWER_LIMIT */ + RAPL_PKG_ENERGY_STATUS = BIT(1), /* 0x611 MSR_PKG_ENERGY_STATUS */ + RAPL_PKG_PERF_STATUS = BIT(2), /* 0x613 MSR_PKG_PERF_STATUS */ + RAPL_PKG_POWER_INFO = BIT(3), /* 0x614 MSR_PKG_POWER_INFO */ + RAPL_DRAM_POWER_LIMIT = BIT(4), /* 0x618 MSR_DRAM_POWER_LIMIT */ + RAPL_DRAM_ENERGY_STATUS = BIT(5), /* 0x619 MSR_DRAM_ENERGY_STATUS */ + RAPL_DRAM_PERF_STATUS = BIT(6), /* 0x61b MSR_DRAM_PERF_STATUS */ + RAPL_DRAM_POWER_INFO = BIT(7), /* 0x61c MSR_DRAM_POWER_INFO */ + RAPL_CORE_POWER_LIMIT = BIT(8), /* 0x638 MSR_PP0_POWER_LIMIT */ + RAPL_CORE_ENERGY_STATUS = BIT(9), /* 0x639 MSR_PP0_ENERGY_STATUS */ + RAPL_CORE_POLICY = BIT(10), /* 0x63a MSR_PP0_POLICY */ + RAPL_GFX_POWER_LIMIT = BIT(11), /* 0x640 MSR_PP1_POWER_LIMIT */ + RAPL_GFX_ENERGY_STATUS = BIT(12), /* 0x641 MSR_PP1_ENERGY_STATUS */ + RAPL_GFX_POLICY = BIT(13), /* 0x642 MSR_PP1_POLICY */ + RAPL_AMD_PWR_UNIT = BIT(14), /* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */ + RAPL_AMD_CORE_ENERGY_STAT = BIT(15), /* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */ + RAPL_AMD_PKG_ENERGY_STAT = BIT(16), /* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */ + RAPL_PER_CORE_ENERGY = BIT(17), /* Indicates cores energy collection is per-core, not per-package. */ +}; + +#define RAPL_PKG (RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT) +#define RAPL_DRAM (RAPL_DRAM_ENERGY_STATUS | RAPL_DRAM_POWER_LIMIT) +#define RAPL_CORE (RAPL_CORE_ENERGY_STATUS | RAPL_CORE_POWER_LIMIT) +#define RAPL_GFX (RAPL_GFX_POWER_LIMIT | RAPL_GFX_ENERGY_STATUS) + +#define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO) +#define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO) +#define RAPL_CORE_ALL (RAPL_CORE | RAPL_CORE_POLICY) +#define RAPL_GFX_ALL (RAPL_GFX | RAPL_GFX_POLIGY) + +#define RAPL_AMD_F17H (RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT) + static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, @@ -712,42 +746,6 @@ void probe_platform_features(unsigned int family, unsigned int model) /* Model specific support End */ -#define RAPL_PKG (1 << 0) - /* 0x610 MSR_PKG_POWER_LIMIT */ - /* 0x611 MSR_PKG_ENERGY_STATUS */ -#define RAPL_PKG_PERF_STATUS (1 << 1) - /* 0x613 MSR_PKG_PERF_STATUS */ -#define RAPL_PKG_POWER_INFO (1 << 2) - /* 0x614 MSR_PKG_POWER_INFO */ - -#define RAPL_DRAM (1 << 3) - /* 0x618 MSR_DRAM_POWER_LIMIT */ - /* 0x619 MSR_DRAM_ENERGY_STATUS */ -#define RAPL_DRAM_PERF_STATUS (1 << 4) - /* 0x61b MSR_DRAM_PERF_STATUS */ -#define RAPL_DRAM_POWER_INFO (1 << 5) - /* 0x61c MSR_DRAM_POWER_INFO */ - -#define RAPL_CORES_POWER_LIMIT (1 << 6) - /* 0x638 MSR_PP0_POWER_LIMIT */ -#define RAPL_CORE_POLICY (1 << 7) - /* 0x63a MSR_PP0_POLICY */ - -#define RAPL_GFX (1 << 8) - /* 0x640 MSR_PP1_POWER_LIMIT */ - /* 0x641 MSR_PP1_ENERGY_STATUS */ - /* 0x642 MSR_PP1_POLICY */ - -#define RAPL_CORES_ENERGY_STATUS (1 << 9) - /* 0x639 MSR_PP0_ENERGY_STATUS */ -#define RAPL_PER_CORE_ENERGY (1 << 10) - /* Indicates cores energy collection is per-core, - * not per-package. */ -#define RAPL_AMD_F17H (1 << 11) - /* 0xc0010299 MSR_RAPL_PWR_UNIT */ - /* 0xc001029a MSR_CORE_ENERGY_STAT */ - /* 0xc001029b MSR_PKG_ENERGY_STAT */ -#define RAPL_CORES (RAPL_CORES_ENERGY_STATUS | RAPL_CORES_POWER_LIMIT) #define TJMAX_DEFAULT 100 /* MSRs that are not yet in the kernel-provided header. */ @@ -948,7 +946,7 @@ int idx_valid(int idx) case IDX_DRAM_ENERGY: return do_rapl & RAPL_DRAM; case IDX_PP0_ENERGY: - return do_rapl & RAPL_CORES_ENERGY_STATUS; + return do_rapl & RAPL_CORE_ENERGY_STATUS; case IDX_PP1_ENERGY: return do_rapl & RAPL_GFX; case IDX_PKG_PERF: @@ -2710,7 +2708,7 @@ retry: return -13; p->energy_pkg = msr; } - if (do_rapl & RAPL_CORES_ENERGY_STATUS) { + if (do_rapl & RAPL_CORE_ENERGY_STATUS) { if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr)) return -14; p->energy_cores = msr; @@ -4810,7 +4808,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) case INTEL_FAM6_HASWELL_G: /* HSW */ case INTEL_FAM6_BROADWELL: /* BDW */ case INTEL_FAM6_BROADWELL_G: /* BDW */ - do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; + do_rapl = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO; if (rapl_joules) { BIC_PRESENT(BIC_Pkg_J); BIC_PRESENT(BIC_Cor_J); @@ -4830,9 +4828,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) BIC_PRESENT(BIC_PkgWatt); break; case INTEL_FAM6_ATOM_TREMONT: /* EHL */ - do_rapl = - RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS - | RAPL_GFX | RAPL_PKG_POWER_INFO; + do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX; if (rapl_joules) { BIC_PRESENT(BIC_Pkg_J); BIC_PRESENT(BIC_Cor_J); @@ -4846,7 +4842,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) } break; case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */ - do_rapl = RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; + do_rapl = RAPL_PKG_ALL; BIC_PRESENT(BIC_PKG__); if (rapl_joules) BIC_PRESENT(BIC_Pkg_J); @@ -4855,9 +4851,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) break; case INTEL_FAM6_SKYLAKE_L: /* SKL */ case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - do_rapl = - RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS - | RAPL_GFX | RAPL_PKG_POWER_INFO; + do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX; BIC_PRESENT(BIC_PKG__); BIC_PRESENT(BIC_RAM__); if (rapl_joules) { @@ -4878,9 +4872,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) case INTEL_FAM6_ICELAKE_X: /* ICX */ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ - do_rapl = - RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | - RAPL_PKG_POWER_INFO; + do_rapl = RAPL_PKG_ALL | RAPL_DRAM_ALL; BIC_PRESENT(BIC_PKG__); BIC_PRESENT(BIC_RAM__); if (rapl_joules) { @@ -4893,9 +4885,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) break; case INTEL_FAM6_SANDYBRIDGE_X: case INTEL_FAM6_IVYBRIDGE_X: - do_rapl = - RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | - RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO; + do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL; BIC_PRESENT(BIC_PKG__); BIC_PRESENT(BIC_RAM__); if (rapl_joules) { @@ -4910,7 +4900,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) break; case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ - do_rapl = RAPL_PKG | RAPL_CORES; + do_rapl = RAPL_PKG | RAPL_CORE; if (rapl_joules) { BIC_PRESENT(BIC_Pkg_J); BIC_PRESENT(BIC_Cor_J); @@ -4920,9 +4910,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) } break; case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ - do_rapl = - RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | - RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS; + do_rapl = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS; BIC_PRESENT(BIC_PKG__); BIC_PRESENT(BIC_RAM__); if (rapl_joules) { @@ -5195,7 +5183,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF); } - if (do_rapl & RAPL_CORES_POWER_LIMIT) { + if (do_rapl & RAPL_CORE_POWER_LIMIT) { if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) return -9; fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", -- cgit v1.2.3 From a98f886035d5f7e0ec66036dd6bf98b40e75b692 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 26 Aug 2023 14:57:12 +0800 Subject: tools/power/turbostat: Simplify the logic for RAPL enumeration The support for each RAPL domains, as well as the support for the perf status of each RAPL domains, can be detected by checking the availabilities of the corresponding RAPL MSRs. Change the code accordingly and remove the hardcoded logic for each model. Note that this also fixes the INTEL_FAM6_ATOM_TREMONT model, which has RAPL_PKG_PERF_STATUS and MSR_DRAM_PERF_STATUS but doesn't have BIC_PKG__ and BIC_RAM__ set. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 99 ++++++++--------------------------- 1 file changed, 22 insertions(+), 77 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 4829e8289feb..b2da36437b12 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4809,62 +4809,20 @@ void rapl_probe_intel(unsigned int family, unsigned int model) case INTEL_FAM6_BROADWELL: /* BDW */ case INTEL_FAM6_BROADWELL_G: /* BDW */ do_rapl = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO; - if (rapl_joules) { - BIC_PRESENT(BIC_Pkg_J); - BIC_PRESENT(BIC_Cor_J); - BIC_PRESENT(BIC_GFX_J); - } else { - BIC_PRESENT(BIC_PkgWatt); - BIC_PRESENT(BIC_CorWatt); - BIC_PRESENT(BIC_GFXWatt); - } break; case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ case INTEL_FAM6_ATOM_GOLDMONT_PLUS: do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO; - if (rapl_joules) - BIC_PRESENT(BIC_Pkg_J); - else - BIC_PRESENT(BIC_PkgWatt); break; case INTEL_FAM6_ATOM_TREMONT: /* EHL */ do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX; - if (rapl_joules) { - BIC_PRESENT(BIC_Pkg_J); - BIC_PRESENT(BIC_Cor_J); - BIC_PRESENT(BIC_RAM_J); - BIC_PRESENT(BIC_GFX_J); - } else { - BIC_PRESENT(BIC_PkgWatt); - BIC_PRESENT(BIC_CorWatt); - BIC_PRESENT(BIC_RAMWatt); - BIC_PRESENT(BIC_GFXWatt); - } break; case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */ do_rapl = RAPL_PKG_ALL; - BIC_PRESENT(BIC_PKG__); - if (rapl_joules) - BIC_PRESENT(BIC_Pkg_J); - else - BIC_PRESENT(BIC_PkgWatt); break; case INTEL_FAM6_SKYLAKE_L: /* SKL */ case INTEL_FAM6_CANNONLAKE_L: /* CNL */ do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX; - BIC_PRESENT(BIC_PKG__); - BIC_PRESENT(BIC_RAM__); - if (rapl_joules) { - BIC_PRESENT(BIC_Pkg_J); - BIC_PRESENT(BIC_Cor_J); - BIC_PRESENT(BIC_RAM_J); - BIC_PRESENT(BIC_GFX_J); - } else { - BIC_PRESENT(BIC_PkgWatt); - BIC_PRESENT(BIC_CorWatt); - BIC_PRESENT(BIC_RAMWatt); - BIC_PRESENT(BIC_GFXWatt); - } break; case INTEL_FAM6_HASWELL_X: /* HSX */ case INTEL_FAM6_BROADWELL_X: /* BDX */ @@ -4873,60 +4831,47 @@ void rapl_probe_intel(unsigned int family, unsigned int model) case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ do_rapl = RAPL_PKG_ALL | RAPL_DRAM_ALL; - BIC_PRESENT(BIC_PKG__); - BIC_PRESENT(BIC_RAM__); - if (rapl_joules) { - BIC_PRESENT(BIC_Pkg_J); - BIC_PRESENT(BIC_RAM_J); - } else { - BIC_PRESENT(BIC_PkgWatt); - BIC_PRESENT(BIC_RAMWatt); - } break; case INTEL_FAM6_SANDYBRIDGE_X: case INTEL_FAM6_IVYBRIDGE_X: do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL; - BIC_PRESENT(BIC_PKG__); - BIC_PRESENT(BIC_RAM__); - if (rapl_joules) { - BIC_PRESENT(BIC_Pkg_J); - BIC_PRESENT(BIC_Cor_J); - BIC_PRESENT(BIC_RAM_J); - } else { - BIC_PRESENT(BIC_PkgWatt); - BIC_PRESENT(BIC_CorWatt); - BIC_PRESENT(BIC_RAMWatt); - } break; case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ do_rapl = RAPL_PKG | RAPL_CORE; - if (rapl_joules) { - BIC_PRESENT(BIC_Pkg_J); - BIC_PRESENT(BIC_Cor_J); - } else { - BIC_PRESENT(BIC_PkgWatt); - BIC_PRESENT(BIC_CorWatt); - } break; case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ do_rapl = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS; - BIC_PRESENT(BIC_PKG__); - BIC_PRESENT(BIC_RAM__); - if (rapl_joules) { + break; + default: + return; + } + + if (rapl_joules) { + if (do_rapl & RAPL_PKG_ENERGY_STATUS) BIC_PRESENT(BIC_Pkg_J); + if (do_rapl & RAPL_CORE_ENERGY_STATUS) BIC_PRESENT(BIC_Cor_J); + if (do_rapl & RAPL_DRAM_ENERGY_STATUS) BIC_PRESENT(BIC_RAM_J); - } else { + if (do_rapl & RAPL_GFX_ENERGY_STATUS) + BIC_PRESENT(BIC_GFX_J); + } else { + if (do_rapl & RAPL_PKG_ENERGY_STATUS) BIC_PRESENT(BIC_PkgWatt); + if (do_rapl & RAPL_CORE_ENERGY_STATUS) BIC_PRESENT(BIC_CorWatt); + if (do_rapl & RAPL_DRAM_ENERGY_STATUS) BIC_PRESENT(BIC_RAMWatt); - } - break; - default: - return; + if (do_rapl & RAPL_GFX_ENERGY_STATUS) + BIC_PRESENT(BIC_GFXWatt); } + if (do_rapl & RAPL_PKG_PERF_STATUS) + BIC_PRESENT(BIC_PKG__); + if (do_rapl & RAPL_DRAM_PERF_STATUS) + BIC_PRESENT(BIC_RAM__); + /* units on package 0, verify later other packages match */ if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr)) return; -- cgit v1.2.3 From 86ba263d9b72b7766a99059e9b3bd104d089b7fa Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 28 Aug 2023 15:09:40 +0800 Subject: tools/power/turbostat: Abstract RAPL MSRs support Abstract the support for RAPL MSRs. Delete CPU model checks in rapl_probe_intel(). Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 189 +++++++++++++++------------------- 1 file changed, 85 insertions(+), 104 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index b2da36437b12..90e1abe96dd5 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -288,6 +288,7 @@ struct platform_features { bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ + int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ }; @@ -414,6 +415,7 @@ static const struct platform_features snb_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; static const struct platform_features snx_features = { @@ -423,6 +425,7 @@ static const struct platform_features snx_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, }; static const struct platform_features ivb_features = { @@ -433,6 +436,7 @@ static const struct platform_features ivb_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; static const struct platform_features ivx_features = { @@ -442,6 +446,7 @@ static const struct platform_features ivx_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE | TRL_LIMIT1, + .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, }; static const struct platform_features hsw_features = { @@ -453,6 +458,7 @@ static const struct platform_features hsw_features = { .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, + .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; static const struct platform_features hsx_features = { @@ -464,6 +470,7 @@ static const struct platform_features hsx_features = { .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, .plr_msrs = PLR_CORE | PLR_RING, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; static const struct platform_features hswl_features = { @@ -475,6 +482,7 @@ static const struct platform_features hswl_features = { .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, + .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; static const struct platform_features hswg_features = { @@ -486,6 +494,7 @@ static const struct platform_features hswg_features = { .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, + .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; static const struct platform_features bdw_features = { @@ -496,6 +505,7 @@ static const struct platform_features bdw_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; static const struct platform_features bdwg_features = { @@ -506,6 +516,7 @@ static const struct platform_features bdwg_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; static const struct platform_features bdx_features = { @@ -517,6 +528,7 @@ static const struct platform_features bdx_features = { .cst_limit = CST_LIMIT_HSW, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; static const struct platform_features skl_features = { @@ -529,6 +541,7 @@ static const struct platform_features skl_features = { .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, + .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, }; static const struct platform_features cnl_features = { @@ -540,6 +553,7 @@ static const struct platform_features cnl_features = { .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, + .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, }; static const struct platform_features skx_features = { @@ -551,6 +565,7 @@ static const struct platform_features skx_features = { .cst_limit = CST_LIMIT_SKX, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; static const struct platform_features icx_features = { @@ -561,6 +576,7 @@ static const struct platform_features icx_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_ICX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; static const struct platform_features spr_features = { @@ -571,6 +587,7 @@ static const struct platform_features spr_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_SKX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; static const struct platform_features slv_features = { @@ -578,6 +595,7 @@ static const struct platform_features slv_features = { .bclk_freq = BCLK_SLV, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_ATOM, + .rapl_msrs = RAPL_PKG | RAPL_CORE, }; static const struct platform_features slvd_features = { @@ -586,6 +604,7 @@ static const struct platform_features slvd_features = { .bclk_freq = BCLK_SLV, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG | RAPL_CORE, }; static const struct platform_features amt_features = { @@ -602,6 +621,7 @@ static const struct platform_features gmt_features = { .crystal_freq = 19200000, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, + .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, }; static const struct platform_features gmtd_features = { @@ -611,6 +631,7 @@ static const struct platform_features gmtd_features = { .crystal_freq = 25000000, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, }; static const struct platform_features gmtp_features = { @@ -620,6 +641,7 @@ static const struct platform_features gmtp_features = { .crystal_freq = 19200000, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, }; static const struct platform_features tmt_features = { @@ -628,6 +650,7 @@ static const struct platform_features tmt_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, + .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, }; static const struct platform_features tmtd_features = { @@ -636,6 +659,7 @@ static const struct platform_features tmtd_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, + .rapl_msrs = RAPL_PKG_ALL, }; static const struct platform_features knl_features = { @@ -645,6 +669,7 @@ static const struct platform_features knl_features = { .bclk_freq = BCLK_100MHZ, .cst_limit = CST_LIMIT_KNL, .trl_msrs = TRL_KNL, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; static const struct platform_features default_features = { @@ -653,6 +678,10 @@ static const struct platform_features default_features = { static const struct platform_features amd_features = { }; +static const struct platform_features amd_features_with_rapl = { + .rapl_msrs = RAPL_AMD_F17H, +}; + static const struct platform_data turbostat_pdata[] = { { INTEL_FAM6_NEHALEM, &nhm_features }, { INTEL_FAM6_NEHALEM_G, &nhm_features }, @@ -728,6 +757,17 @@ void probe_platform_features(unsigned int family, unsigned int model) if (authentic_amd || hygon_genuine) { platform = &amd_features; + + if (max_extended_level >= 0x80000007) { + unsigned int eax, ebx, ecx, edx; + + __cpuid(0x80000007, eax, ebx, ecx, edx); + /* RAPL (Fam 17h+) */ + if ((edx & (1 << 14)) && family >= 0x17) { + platform = &amd_features_with_rapl; + do_rapl = RAPL_PER_CORE_ENERGY; + } + } return; } @@ -882,7 +922,7 @@ off_t idx_to_offset(int idx) switch (idx) { case IDX_PKG_ENERGY: - if (do_rapl & RAPL_AMD_F17H) + if (platform->rapl_msrs & RAPL_AMD_F17H) offset = MSR_PKG_ENERGY_STAT; else offset = MSR_PKG_ENERGY_STATUS; @@ -942,17 +982,17 @@ int idx_valid(int idx) { switch (idx) { case IDX_PKG_ENERGY: - return do_rapl & (RAPL_PKG | RAPL_AMD_F17H); + return platform->rapl_msrs & (RAPL_PKG | RAPL_AMD_F17H); case IDX_DRAM_ENERGY: - return do_rapl & RAPL_DRAM; + return platform->rapl_msrs & RAPL_DRAM; case IDX_PP0_ENERGY: - return do_rapl & RAPL_CORE_ENERGY_STATUS; + return platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS; case IDX_PP1_ENERGY: - return do_rapl & RAPL_GFX; + return platform->rapl_msrs & RAPL_GFX; case IDX_PKG_PERF: - return do_rapl & RAPL_PKG_PERF_STATUS; + return platform->rapl_msrs & RAPL_PKG_PERF_STATUS; case IDX_DRAM_PERF: - return do_rapl & RAPL_DRAM_PERF_STATUS; + return platform->rapl_msrs & RAPL_DRAM_PERF_STATUS; default: return 0; } @@ -1330,10 +1370,10 @@ void print_header(char *delim) if (DO_BIC(BIC_CORE_THROT_CNT)) outp += sprintf(outp, "%sCoreThr", (printed++ ? delim : "")); - if (do_rapl && !rapl_joules) { + if (platform->rapl_msrs && !rapl_joules) { if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY)) outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : "")); - } else if (do_rapl && rapl_joules) { + } else if (platform->rapl_msrs && rapl_joules) { if (DO_BIC(BIC_Cor_J) && (do_rapl & RAPL_PER_CORE_ENERGY)) outp += sprintf(outp, "%sCor_J", (printed++ ? delim : "")); } @@ -1392,7 +1432,7 @@ void print_header(char *delim) if (DO_BIC(BIC_SYS_LPI)) outp += sprintf(outp, "%sSYS%%LPI", (printed++ ? delim : "")); - if (do_rapl && !rapl_joules) { + if (platform->rapl_msrs && !rapl_joules) { if (DO_BIC(BIC_PkgWatt)) outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : "")); if (DO_BIC(BIC_CorWatt) && !(do_rapl & RAPL_PER_CORE_ENERGY)) @@ -1405,7 +1445,7 @@ void print_header(char *delim) outp += sprintf(outp, "%sPKG_%%", (printed++ ? delim : "")); if (DO_BIC(BIC_RAM__)) outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : "")); - } else if (do_rapl && rapl_joules) { + } else if (platform->rapl_msrs && rapl_joules) { if (DO_BIC(BIC_Pkg_J)) outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : "")); if (DO_BIC(BIC_Cor_J) && !(do_rapl & RAPL_PER_CORE_ENERGY)) @@ -2638,7 +2678,7 @@ retry: if (DO_BIC(BIC_CORE_THROT_CNT)) get_core_throt_cnt(cpu, &c->core_throt_cnt); - if (do_rapl & RAPL_AMD_F17H) { + if (platform->rapl_msrs & RAPL_AMD_F17H) { if (get_msr(cpu, MSR_CORE_ENERGY_STAT, &msr)) return -14; c->core_energy = msr & 0xFFFFFFFF; @@ -2703,37 +2743,37 @@ retry: if (DO_BIC(BIC_SYS_LPI)) p->sys_lpi = cpuidle_cur_sys_lpi_us; - if (do_rapl & RAPL_PKG) { + if (platform->rapl_msrs & RAPL_PKG) { if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr)) return -13; p->energy_pkg = msr; } - if (do_rapl & RAPL_CORE_ENERGY_STATUS) { + if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) { if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr)) return -14; p->energy_cores = msr; } - if (do_rapl & RAPL_DRAM) { + if (platform->rapl_msrs & RAPL_DRAM) { if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr)) return -15; p->energy_dram = msr; } - if (do_rapl & RAPL_GFX) { + if (platform->rapl_msrs & RAPL_GFX) { if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr)) return -16; p->energy_gfx = msr; } - if (do_rapl & RAPL_PKG_PERF_STATUS) { + if (platform->rapl_msrs & RAPL_PKG_PERF_STATUS) { if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr)) return -16; p->rapl_pkg_perf_status = msr; } - if (do_rapl & RAPL_DRAM_PERF_STATUS) { + if (platform->rapl_msrs & RAPL_DRAM_PERF_STATUS) { if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr)) return -16; p->rapl_dram_perf_status = msr; } - if (do_rapl & RAPL_AMD_F17H) { + if (platform->rapl_msrs & RAPL_AMD_F17H) { if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr)) return -13; p->energy_pkg = msr; @@ -4750,7 +4790,7 @@ double get_tdp_intel(unsigned int model) { unsigned long long msr; - if (do_rapl & RAPL_PKG_POWER_INFO) + if (platform->rapl_msrs & RAPL_PKG_POWER_INFO) if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr)) return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; @@ -4791,85 +4831,35 @@ static double rapl_dram_energy_units_probe(int model, double rapl_energy_units) } } -void rapl_probe_intel(unsigned int family, unsigned int model) +void rapl_probe_intel(unsigned int model) { unsigned long long msr; unsigned int time_unit; double tdp; - if (family != 6) - return; - - switch (model) { - case INTEL_FAM6_SANDYBRIDGE: - case INTEL_FAM6_IVYBRIDGE: - case INTEL_FAM6_HASWELL: /* HSW */ - case INTEL_FAM6_HASWELL_L: /* HSW */ - case INTEL_FAM6_HASWELL_G: /* HSW */ - case INTEL_FAM6_BROADWELL: /* BDW */ - case INTEL_FAM6_BROADWELL_G: /* BDW */ - do_rapl = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO; - break; - case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GOLDMONT_PLUS: - do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO; - break; - case INTEL_FAM6_ATOM_TREMONT: /* EHL */ - do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX; - break; - case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */ - do_rapl = RAPL_PKG_ALL; - break; - case INTEL_FAM6_SKYLAKE_L: /* SKL */ - case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX; - break; - case INTEL_FAM6_HASWELL_X: /* HSX */ - case INTEL_FAM6_BROADWELL_X: /* BDX */ - case INTEL_FAM6_SKYLAKE_X: /* SKX */ - case INTEL_FAM6_ICELAKE_X: /* ICX */ - case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ - case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ - do_rapl = RAPL_PKG_ALL | RAPL_DRAM_ALL; - break; - case INTEL_FAM6_SANDYBRIDGE_X: - case INTEL_FAM6_IVYBRIDGE_X: - do_rapl = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL; - break; - case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ - case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ - do_rapl = RAPL_PKG | RAPL_CORE; - break; - case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ - do_rapl = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS; - break; - default: - return; - } - if (rapl_joules) { - if (do_rapl & RAPL_PKG_ENERGY_STATUS) + if (platform->rapl_msrs & RAPL_PKG_ENERGY_STATUS) BIC_PRESENT(BIC_Pkg_J); - if (do_rapl & RAPL_CORE_ENERGY_STATUS) + if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) BIC_PRESENT(BIC_Cor_J); - if (do_rapl & RAPL_DRAM_ENERGY_STATUS) + if (platform->rapl_msrs & RAPL_DRAM_ENERGY_STATUS) BIC_PRESENT(BIC_RAM_J); - if (do_rapl & RAPL_GFX_ENERGY_STATUS) + if (platform->rapl_msrs & RAPL_GFX_ENERGY_STATUS) BIC_PRESENT(BIC_GFX_J); } else { - if (do_rapl & RAPL_PKG_ENERGY_STATUS) + if (platform->rapl_msrs & RAPL_PKG_ENERGY_STATUS) BIC_PRESENT(BIC_PkgWatt); - if (do_rapl & RAPL_CORE_ENERGY_STATUS) + if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) BIC_PRESENT(BIC_CorWatt); - if (do_rapl & RAPL_DRAM_ENERGY_STATUS) + if (platform->rapl_msrs & RAPL_DRAM_ENERGY_STATUS) BIC_PRESENT(BIC_RAMWatt); - if (do_rapl & RAPL_GFX_ENERGY_STATUS) + if (platform->rapl_msrs & RAPL_GFX_ENERGY_STATUS) BIC_PRESENT(BIC_GFXWatt); } - if (do_rapl & RAPL_PKG_PERF_STATUS) + if (platform->rapl_msrs & RAPL_PKG_PERF_STATUS) BIC_PRESENT(BIC_PKG__); - if (do_rapl & RAPL_DRAM_PERF_STATUS) + if (platform->rapl_msrs & RAPL_DRAM_PERF_STATUS) BIC_PRESENT(BIC_RAM__); /* units on package 0, verify later other packages match */ @@ -4900,22 +4890,10 @@ void rapl_probe_intel(unsigned int family, unsigned int model) void rapl_probe_amd(unsigned int family, unsigned int model) { unsigned long long msr; - unsigned int eax, ebx, ecx, edx; - unsigned int has_rapl = 0; double tdp; UNUSED(model); - if (max_extended_level >= 0x80000007) { - __cpuid(0x80000007, eax, ebx, ecx, edx); - /* RAPL (Fam 17h+) */ - has_rapl = edx & (1 << 14); - } - - if (!has_rapl || family < 0x17) - return; - - do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY; if (rapl_joules) { BIC_PRESENT(BIC_Pkg_J); BIC_PRESENT(BIC_Cor_J); @@ -4941,12 +4919,15 @@ void rapl_probe_amd(unsigned int family, unsigned int model) /* * rapl_probe() * - * sets do_rapl, rapl_power_units, rapl_energy_units, rapl_time_units + * sets rapl_power_units, rapl_energy_units, rapl_time_units */ void rapl_probe(unsigned int family, unsigned int model) { + if (!platform->rapl_msrs) + return; + if (genuine_intel) - rapl_probe_intel(family, model); + rapl_probe_intel(model); if (authentic_amd || hygon_genuine) rapl_probe_amd(family, model); } @@ -5040,7 +5021,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) UNUSED(c); UNUSED(p); - if (!do_rapl) + if (!platform->rapl_msrs) return 0; /* RAPL counters are per package, so print only for 1st thread/package */ @@ -5053,7 +5034,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) return -1; } - if (do_rapl & RAPL_AMD_F17H) { + if (platform->rapl_msrs & RAPL_AMD_F17H) { msr_name = "MSR_RAPL_PWR_UNIT"; if (get_msr(cpu, MSR_RAPL_PWR_UNIT, &msr)) return -1; @@ -5066,7 +5047,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) fprintf(outf, "cpu%d: %s: 0x%08llx (%f Watts, %f Joules, %f sec.)\n", cpu, msr_name, msr, rapl_power_units, rapl_energy_units, rapl_time_units); - if (do_rapl & RAPL_PKG_POWER_INFO) { + if (platform->rapl_msrs & RAPL_PKG_POWER_INFO) { if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr)) return -5; @@ -5079,7 +5060,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); } - if (do_rapl & RAPL_PKG) { + if (platform->rapl_msrs & RAPL_PKG) { if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr)) return -9; @@ -5103,7 +5084,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) cpu, ((msr >> 0) & 0x1FFF) * rapl_power_units, (msr >> 31) & 1 ? "" : "UN"); } - if (do_rapl & RAPL_DRAM_POWER_INFO) { + if (platform->rapl_msrs & RAPL_DRAM_POWER_INFO) { if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr)) return -6; @@ -5114,7 +5095,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); } - if (do_rapl & RAPL_DRAM) { + if (platform->rapl_msrs & RAPL_DRAM) { if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr)) return -9; fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", @@ -5122,20 +5103,20 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) print_power_limit_msr(cpu, msr, "DRAM Limit"); } - if (do_rapl & RAPL_CORE_POLICY) { + if (platform->rapl_msrs & RAPL_CORE_POLICY) { if (get_msr(cpu, MSR_PP0_POLICY, &msr)) return -7; fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF); } - if (do_rapl & RAPL_CORE_POWER_LIMIT) { + if (platform->rapl_msrs & RAPL_CORE_POWER_LIMIT) { if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) return -9; fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n", cpu, msr, (msr >> 31) & 1 ? "" : "UN"); print_power_limit_msr(cpu, msr, "Cores Limit"); } - if (do_rapl & RAPL_GFX) { + if (platform->rapl_msrs & RAPL_GFX) { if (get_msr(cpu, MSR_PP1_POLICY, &msr)) return -8; -- cgit v1.2.3 From e338831b14d2da921348c8c4055b9f2c94effe73 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 21:37:46 +0800 Subject: tools/power/turbostat: Abstract Per Core RAPL support Abstract the support for Per Core RAPL. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 90e1abe96dd5..6314c40dc15b 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -245,7 +245,6 @@ double tsc_tweak = 1.0; unsigned int show_pkg_only; unsigned int show_core_only; char *output_buffer, *outp; -unsigned int do_rapl; unsigned int do_dts; unsigned int do_ptm; unsigned int do_ipc; @@ -289,6 +288,7 @@ struct platform_features { int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ + bool has_per_core_rapl; /* Indicates cores energy collection is per-core, not per-package. AMD specific for now */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ }; @@ -378,7 +378,6 @@ enum rapl_msrs { RAPL_AMD_PWR_UNIT = BIT(14), /* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */ RAPL_AMD_CORE_ENERGY_STAT = BIT(15), /* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */ RAPL_AMD_PKG_ENERGY_STAT = BIT(16), /* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */ - RAPL_PER_CORE_ENERGY = BIT(17), /* Indicates cores energy collection is per-core, not per-package. */ }; #define RAPL_PKG (RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT) @@ -680,6 +679,7 @@ static const struct platform_features amd_features = { static const struct platform_features amd_features_with_rapl = { .rapl_msrs = RAPL_AMD_F17H, + .has_per_core_rapl = 1, }; static const struct platform_data turbostat_pdata[] = { @@ -763,10 +763,8 @@ void probe_platform_features(unsigned int family, unsigned int model) __cpuid(0x80000007, eax, ebx, ecx, edx); /* RAPL (Fam 17h+) */ - if ((edx & (1 << 14)) && family >= 0x17) { + if ((edx & (1 << 14)) && family >= 0x17) platform = &amd_features_with_rapl; - do_rapl = RAPL_PER_CORE_ENERGY; - } } return; } @@ -1371,10 +1369,10 @@ void print_header(char *delim) outp += sprintf(outp, "%sCoreThr", (printed++ ? delim : "")); if (platform->rapl_msrs && !rapl_joules) { - if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY)) + if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl) outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : "")); } else if (platform->rapl_msrs && rapl_joules) { - if (DO_BIC(BIC_Cor_J) && (do_rapl & RAPL_PER_CORE_ENERGY)) + if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl) outp += sprintf(outp, "%sCor_J", (printed++ ? delim : "")); } @@ -1435,7 +1433,7 @@ void print_header(char *delim) if (platform->rapl_msrs && !rapl_joules) { if (DO_BIC(BIC_PkgWatt)) outp += sprintf(outp, "%sPkgWatt", (printed++ ? delim : "")); - if (DO_BIC(BIC_CorWatt) && !(do_rapl & RAPL_PER_CORE_ENERGY)) + if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl) outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : "")); if (DO_BIC(BIC_GFXWatt)) outp += sprintf(outp, "%sGFXWatt", (printed++ ? delim : "")); @@ -1448,7 +1446,7 @@ void print_header(char *delim) } else if (platform->rapl_msrs && rapl_joules) { if (DO_BIC(BIC_Pkg_J)) outp += sprintf(outp, "%sPkg_J", (printed++ ? delim : "")); - if (DO_BIC(BIC_Cor_J) && !(do_rapl & RAPL_PER_CORE_ENERGY)) + if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl) outp += sprintf(outp, "%sCor_J", (printed++ ? delim : "")); if (DO_BIC(BIC_GFX_J)) outp += sprintf(outp, "%sGFX_J", (printed++ ? delim : "")); @@ -1750,10 +1748,10 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data fmt8 = "%s%.2f"; - if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY)) + if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float); - if (DO_BIC(BIC_Cor_J) && (do_rapl & RAPL_PER_CORE_ENERGY)) + if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units); /* print per-package data only for 1st core in package */ @@ -1818,7 +1816,7 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float); - if (DO_BIC(BIC_CorWatt) && !(do_rapl & RAPL_PER_CORE_ENERGY)) + if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float); if (DO_BIC(BIC_GFXWatt)) @@ -1830,7 +1828,7 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data p->energy_dram * rapl_dram_energy_units / interval_float); if (DO_BIC(BIC_Pkg_J)) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units); - if (DO_BIC(BIC_Cor_J) && !(do_rapl & RAPL_PER_CORE_ENERGY)) + if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units); if (DO_BIC(BIC_GFX_J)) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units); -- cgit v1.2.3 From 6d35b8c4a661c849361239fe316035ea952606a3 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 22 Apr 2023 11:59:04 +0800 Subject: tools/power/turbostat: Abstract RAPL divisor support INTEL_FAM6_ATOM_SILVERMONT model needs a divisor to convert the raw Energy Units value from MSR_RAPL_POWER_UNIT. Abstract the support for RAPL divisor. Delete CPU model check in rapl_probe_intel(). Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 6314c40dc15b..a31724335671 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -289,6 +289,7 @@ struct platform_features { int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ bool has_per_core_rapl; /* Indicates cores energy collection is per-core, not per-package. AMD specific for now */ + bool has_rapl_divisor; /* Divisor for Energy unit raw value from MSR_RAPL_POWER_UNIT */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ }; @@ -595,6 +596,7 @@ static const struct platform_features slv_features = { .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, + .has_rapl_divisor = 1, }; static const struct platform_features slvd_features = { @@ -4865,7 +4867,7 @@ void rapl_probe_intel(unsigned int model) return; rapl_power_units = 1.0 / (1 << (msr & 0xF)); - if (model == INTEL_FAM6_ATOM_SILVERMONT) + if (platform->has_rapl_divisor) rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000; else rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); -- cgit v1.2.3 From 9e6f35159cdef148c711d2fb7d5fd2b2b6fb772d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 22 Apr 2023 12:21:58 +0800 Subject: tools/power/turbostat: Abstract fixed DRAM Energy unit support Abstract the support for fixed Dram domain energy unit. Delete rapl_dram_energy_units_probe() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a31724335671..a26ae5a2e2bd 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -290,6 +290,7 @@ struct platform_features { int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ bool has_per_core_rapl; /* Indicates cores energy collection is per-core, not per-package. AMD specific for now */ bool has_rapl_divisor; /* Divisor for Energy unit raw value from MSR_RAPL_POWER_UNIT */ + bool has_fixed_rapl_unit; /* Fixed Energy Unit used for DRAM RAPL Domain */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ }; @@ -471,6 +472,7 @@ static const struct platform_features hsx_features = { .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, .plr_msrs = PLR_CORE | PLR_RING, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, + .has_fixed_rapl_unit = 1, }; static const struct platform_features hswl_features = { @@ -529,6 +531,7 @@ static const struct platform_features bdx_features = { .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, + .has_fixed_rapl_unit = 1, }; static const struct platform_features skl_features = { @@ -566,6 +569,7 @@ static const struct platform_features skx_features = { .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, + .has_fixed_rapl_unit = 1, }; static const struct platform_features icx_features = { @@ -577,6 +581,7 @@ static const struct platform_features icx_features = { .cst_limit = CST_LIMIT_ICX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, + .has_fixed_rapl_unit = 1, }; static const struct platform_features spr_features = { @@ -671,6 +676,7 @@ static const struct platform_features knl_features = { .cst_limit = CST_LIMIT_KNL, .trl_msrs = TRL_KNL, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, + .has_fixed_rapl_unit = 1, }; static const struct platform_features default_features = { @@ -4811,26 +4817,6 @@ double get_tdp_amd(unsigned int family) return 280.0; } -/* - * rapl_dram_energy_units_probe() - * Energy units are either hard-coded, or come from RAPL Energy Unit MSR. - */ -static double rapl_dram_energy_units_probe(int model, double rapl_energy_units) -{ - /* only called for genuine_intel, family 6 */ - - switch (model) { - case INTEL_FAM6_HASWELL_X: /* HSX */ - case INTEL_FAM6_BROADWELL_X: /* BDX */ - case INTEL_FAM6_SKYLAKE_X: /* SKX */ - case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ - case INTEL_FAM6_ICELAKE_X: /* ICX */ - return (rapl_dram_energy_units = 15.3 / 1000000); - default: - return (rapl_energy_units); - } -} - void rapl_probe_intel(unsigned int model) { unsigned long long msr; @@ -4872,7 +4858,10 @@ void rapl_probe_intel(unsigned int model) else rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); - rapl_dram_energy_units = rapl_dram_energy_units_probe(model, rapl_energy_units); + if (platform->has_fixed_rapl_unit) + rapl_dram_energy_units = (15.3 / 1000000); + else + rapl_dram_energy_units = rapl_energy_units; time_unit = msr >> 16 & 0xF; if (time_unit == 0) -- cgit v1.2.3 From 7c60409382a4be05d601e0b45db7b0166845b0cf Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 10:21:10 +0800 Subject: tools/power/turbostat: Abstract hardcoded TDP value Different hardcoded TDP values are used when TDP can not be retrieved from the hardware. Abstract hardcoded TDP value. Delete CPU model checks in get_tdp_intel(). Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a26ae5a2e2bd..45698c3a9e72 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -291,6 +291,7 @@ struct platform_features { bool has_per_core_rapl; /* Indicates cores energy collection is per-core, not per-package. AMD specific for now */ bool has_rapl_divisor; /* Divisor for Energy unit raw value from MSR_RAPL_POWER_UNIT */ bool has_fixed_rapl_unit; /* Fixed Energy Unit used for DRAM RAPL Domain */ + int rapl_quirk_tdp; /* Hardcoded TDP value when cannot be retrieved from hardware */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ }; @@ -602,6 +603,7 @@ static const struct platform_features slv_features = { .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, .has_rapl_divisor = 1, + .rapl_quirk_tdp = 30, }; static const struct platform_features slvd_features = { @@ -611,6 +613,7 @@ static const struct platform_features slvd_features = { .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE, + .rapl_quirk_tdp = 30, }; static const struct platform_features amt_features = { @@ -688,6 +691,7 @@ static const struct platform_features amd_features = { static const struct platform_features amd_features_with_rapl = { .rapl_msrs = RAPL_AMD_F17H, .has_per_core_rapl = 1, + .rapl_quirk_tdp = 280, /* This is the max stock TDP of HEDT/Server Fam17h+ chips */ }; static const struct platform_data turbostat_pdata[] = { @@ -4792,29 +4796,31 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data #define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */ #define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */ +double get_quirk_tdp(void) +{ + if (platform->rapl_quirk_tdp) + return platform->rapl_quirk_tdp; + + return 135.0; +} + double get_tdp_intel(unsigned int model) { unsigned long long msr; + UNUSED(model); + if (platform->rapl_msrs & RAPL_PKG_POWER_INFO) if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr)) return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; - - switch (model) { - case INTEL_FAM6_ATOM_SILVERMONT: - case INTEL_FAM6_ATOM_SILVERMONT_D: - return 30.0; - default: - return 135.0; - } + return get_quirk_tdp(); } double get_tdp_amd(unsigned int family) { UNUSED(family); - /* This is the max stock TDP of HEDT/Server Fam17h+ chips */ - return 280.0; + return get_quirk_tdp(); } void rapl_probe_intel(unsigned int model) -- cgit v1.2.3 From bf1ad57c3f92c551dbfdcecd49797253f55cb7c1 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 10:28:04 +0800 Subject: tools/power/turbostat: Remove unused family/model parameters for RAPL functions RAPL probing can be done without family/model checking. Remove these parameters in rapl probe functions. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 45698c3a9e72..44d7321b004e 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4804,26 +4804,22 @@ double get_quirk_tdp(void) return 135.0; } -double get_tdp_intel(unsigned int model) +double get_tdp_intel(void) { unsigned long long msr; - UNUSED(model); - if (platform->rapl_msrs & RAPL_PKG_POWER_INFO) if (!get_msr(base_cpu, MSR_PKG_POWER_INFO, &msr)) return ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units; return get_quirk_tdp(); } -double get_tdp_amd(unsigned int family) +double get_tdp_amd(void) { - UNUSED(family); - return get_quirk_tdp(); } -void rapl_probe_intel(unsigned int model) +void rapl_probe_intel(void) { unsigned long long msr; unsigned int time_unit; @@ -4875,20 +4871,18 @@ void rapl_probe_intel(unsigned int model) rapl_time_units = 1.0 / (1 << (time_unit)); - tdp = get_tdp_intel(model); + tdp = get_tdp_intel(); rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; if (!quiet) fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); } -void rapl_probe_amd(unsigned int family, unsigned int model) +void rapl_probe_amd(void) { unsigned long long msr; double tdp; - UNUSED(model); - if (rapl_joules) { BIC_PRESENT(BIC_Pkg_J); BIC_PRESENT(BIC_Cor_J); @@ -4904,7 +4898,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model) rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f)); rapl_power_units = ldexp(1.0, -(msr & 0xf)); - tdp = get_tdp_amd(family); + tdp = get_tdp_amd(); rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; if (!quiet) @@ -4916,15 +4910,15 @@ void rapl_probe_amd(unsigned int family, unsigned int model) * * sets rapl_power_units, rapl_energy_units, rapl_time_units */ -void rapl_probe(unsigned int family, unsigned int model) +void rapl_probe(void) { if (!platform->rapl_msrs) return; if (genuine_intel) - rapl_probe_intel(model); + rapl_probe_intel(); if (authentic_amd || hygon_genuine) - rapl_probe_amd(family, model); + rapl_probe_amd(); } void prewake_cstate_probe(unsigned int family, unsigned int model) @@ -5828,7 +5822,7 @@ void process_cpuid() if (!quiet && has_slv_msrs(family, model)) decode_c6_demotion_policy_msr(); - rapl_probe(family, model); + rapl_probe(); prewake_cstate_probe(family, model); if (!quiet) -- cgit v1.2.3 From 485a017c45200ed82518f6cdeea554f77e9a0562 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 10:37:23 +0800 Subject: tools/power/turbostat: Abstract TSC tweak support On some models, the CPU base frequency is different from the TSC frequency, and the aperf/mperf counters are running at CPU base frequency instead of TSC frequency. Abstract support for TSC tweak. Given that tsc_tweak depends on base_hz, move the code to probe_bclk() after base_hz is available. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 44d7321b004e..05385fabc83a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -293,6 +293,7 @@ struct platform_features { bool has_fixed_rapl_unit; /* Fixed Energy Unit used for DRAM RAPL Domain */ int rapl_quirk_tdp; /* Hardcoded TDP value when cannot be retrieved from hardware */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ + bool enable_tsc_tweak; /* Use CPU Base freq instead of TSC freq for aperf/mperf counter */ }; struct platform_data { @@ -546,6 +547,7 @@ static const struct platform_features skl_features = { .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, + .enable_tsc_tweak = 1, }; static const struct platform_features cnl_features = { @@ -558,6 +560,7 @@ static const struct platform_features cnl_features = { .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, + .enable_tsc_tweak = 1, }; static const struct platform_features skx_features = { @@ -660,6 +663,7 @@ static const struct platform_features tmt_features = { .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, + .enable_tsc_tweak = 1, }; static const struct platform_features tmtd_features = { @@ -2934,11 +2938,6 @@ void probe_cst_limit(void) pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; } -static void calculate_tsc_tweak() -{ - tsc_tweak = base_hz / tsc_hz; -} - void prewake_cstate_probe(unsigned int family, unsigned int model); static void dump_platform_info(void) @@ -4198,6 +4197,9 @@ void probe_bclk(void) base_hz = base_ratio * bclk * 1000000; has_base_hz = 1; + + if (platform->enable_tsc_tweak) + tsc_tweak = base_hz / tsc_hz; } /* @@ -5836,9 +5838,6 @@ void process_cpuid() if (!quiet) dump_sysfs_pstate_config(); - if (has_skl_msrs(family, model) || is_ehl(family, model)) - calculate_tsc_tweak(); - if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) BIC_PRESENT(BIC_GFX_rc6); -- cgit v1.2.3 From 3c6a17b8ae44b0116e303402803c173fe2a3da92 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 22:37:37 +0800 Subject: tools/power/turbostat: Add skeleton support for cstate enumeration Add skeleton support for cstate enumeration. Note that the previous logic may override the cstate setting for multiple times for different reasons. The conversion to new cstate enumeration must be done step by step following the previous code order strictly. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 57 ++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 05385fabc83a..6a49eb941fe0 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -283,6 +283,7 @@ struct platform_features { bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */ int bclk_freq; /* CPU base clock */ int crystal_freq; /* Crystal clock to use when not available from CPUID.15 */ + int supported_cstates; /* Core cstates and Package cstates supported */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ @@ -396,6 +397,21 @@ enum rapl_msrs { #define RAPL_AMD_F17H (RAPL_AMD_PWR_UNIT | RAPL_AMD_CORE_ENERGY_STAT | RAPL_AMD_PKG_ENERGY_STAT) +/* For Cstates */ +enum cstates { + CC1 = BIT(0), + CC3 = BIT(1), + CC6 = BIT(2), + CC7 = BIT(3), + PC2 = BIT(4), + PC3 = BIT(5), + PC6 = BIT(6), + PC7 = BIT(7), + PC8 = BIT(8), + PC9 = BIT(9), + PC10 = BIT(10), +}; + static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, @@ -5560,6 +5576,44 @@ void linux_perf_init(void) BIC_PRESENT(BIC_IPC); } +void probe_cstates(void) +{ + probe_cst_limit(); + + if (platform->supported_cstates & CC1) + BIC_PRESENT(BIC_CPU_c1); + + if (platform->supported_cstates & CC3) + BIC_PRESENT(BIC_CPU_c3); + + if (platform->supported_cstates & CC6) + BIC_PRESENT(BIC_CPU_c6); + + if (platform->supported_cstates & CC7) + BIC_PRESENT(BIC_CPU_c7); + + if (platform->supported_cstates & PC2 && (pkg_cstate_limit >= PCL__2)) + BIC_PRESENT(BIC_Pkgpc2); + + if (platform->supported_cstates & PC3 && (pkg_cstate_limit >= PCL__3)) + BIC_PRESENT(BIC_Pkgpc3); + + if (platform->supported_cstates & PC6 && (pkg_cstate_limit >= PCL__6)) + BIC_PRESENT(BIC_Pkgpc6); + + if (platform->supported_cstates & PC7 && (pkg_cstate_limit >= PCL__7)) + BIC_PRESENT(BIC_Pkgpc7); + + if (platform->supported_cstates & PC8 && (pkg_cstate_limit >= PCL__8)) + BIC_PRESENT(BIC_Pkgpc8); + + if (platform->supported_cstates & PC9 && (pkg_cstate_limit >= PCL__9)) + BIC_PRESENT(BIC_Pkgpc9); + + if (platform->supported_cstates & PC10 && (pkg_cstate_limit >= PCL_10)) + BIC_PRESENT(BIC_Pkgpc10); +} + void process_cpuid() { unsigned int eax, ebx, ecx, edx; @@ -5741,7 +5795,8 @@ void process_cpuid() BIC_PRESENT(BIC_IRQ); BIC_PRESENT(BIC_TSC_MHz); - probe_cst_limit(); + probe_cstates(); + if (platform->has_nhm_msrs) { BIC_PRESENT(BIC_CPU_c1); BIC_PRESENT(BIC_CPU_c3); -- cgit v1.2.3 From ce7ddf8af2f96a8a7af4cc2273843518c5810166 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 8 Sep 2023 23:16:27 +0800 Subject: tools/power/turbostat: Adjust cstate for models with .has_nhm_msrs set Enable CC1/CC3/CC6 for platforms with .has_nhm_msrs set. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 6a49eb941fe0..c7345e0c5185 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -416,6 +416,7 @@ static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_NHM, .trl_msrs = TRL_BASE, }; @@ -424,6 +425,7 @@ static const struct platform_features nhx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_NHM, }; @@ -432,6 +434,7 @@ static const struct platform_features snb_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -442,6 +445,7 @@ static const struct platform_features snx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, @@ -453,6 +457,7 @@ static const struct platform_features ivb_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -463,6 +468,7 @@ static const struct platform_features ivx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE | TRL_LIMIT1, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, @@ -474,6 +480,7 @@ static const struct platform_features hsw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -486,6 +493,7 @@ static const struct platform_features hsx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, .plr_msrs = PLR_CORE | PLR_RING, @@ -499,6 +507,7 @@ static const struct platform_features hswl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -511,6 +520,7 @@ static const struct platform_features hswg_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -523,6 +533,7 @@ static const struct platform_features bdw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -534,6 +545,7 @@ static const struct platform_features bdwg_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -545,6 +557,7 @@ static const struct platform_features bdx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, @@ -559,6 +572,7 @@ static const struct platform_features skl_features = { .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 24000000, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -572,6 +586,7 @@ static const struct platform_features cnl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -585,6 +600,7 @@ static const struct platform_features skx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_SKX, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, @@ -598,6 +614,7 @@ static const struct platform_features icx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_ICX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -610,6 +627,7 @@ static const struct platform_features spr_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_SKX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -618,6 +636,7 @@ static const struct platform_features spr_features = { static const struct platform_features slv_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, @@ -629,6 +648,7 @@ static const struct platform_features slvd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE, @@ -638,6 +658,7 @@ static const struct platform_features slvd_features = { static const struct platform_features amt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_AMT, .trl_msrs = TRL_BASE, }; @@ -647,6 +668,7 @@ static const struct platform_features gmt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -657,6 +679,7 @@ static const struct platform_features gmtd_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 25000000, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, @@ -667,6 +690,7 @@ static const struct platform_features gmtp_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -676,6 +700,7 @@ static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -686,6 +711,7 @@ static const struct platform_features tmtd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL, @@ -696,6 +722,7 @@ static const struct platform_features knl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC3 | CC6, .cst_limit = CST_LIMIT_KNL, .trl_msrs = TRL_KNL, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -5797,12 +5824,8 @@ void process_cpuid() probe_cstates(); - if (platform->has_nhm_msrs) { - BIC_PRESENT(BIC_CPU_c1); - BIC_PRESENT(BIC_CPU_c3); - BIC_PRESENT(BIC_CPU_c6); + if (platform->has_nhm_msrs) BIC_PRESENT(BIC_SMI); - } probe_bclk(); do_snb_cstates = has_snb_msrs(family, model); -- cgit v1.2.3 From 942c854d8d0f6c6fc0864a9da5f5e374a8e146e5 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 8 Sep 2023 23:16:56 +0800 Subject: tools/power/turbostat: Adjust cstate for has_snb_msrs() models Enable CC7 and PC2 for has_snb_msrs() models. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 47 ++++++++++++++++------------------- 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index c7345e0c5185..174a8d0750da 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -434,7 +434,7 @@ static const struct platform_features snb_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -445,7 +445,7 @@ static const struct platform_features snx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, @@ -457,7 +457,7 @@ static const struct platform_features ivb_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -468,7 +468,7 @@ static const struct platform_features ivx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE | TRL_LIMIT1, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, @@ -480,7 +480,7 @@ static const struct platform_features hsw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -493,7 +493,7 @@ static const struct platform_features hsx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, .plr_msrs = PLR_CORE | PLR_RING, @@ -507,7 +507,7 @@ static const struct platform_features hswl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -520,7 +520,7 @@ static const struct platform_features hswg_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -533,7 +533,7 @@ static const struct platform_features bdw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -545,7 +545,7 @@ static const struct platform_features bdwg_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -557,7 +557,7 @@ static const struct platform_features bdx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, @@ -572,7 +572,7 @@ static const struct platform_features skl_features = { .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 24000000, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -586,7 +586,7 @@ static const struct platform_features cnl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -600,7 +600,7 @@ static const struct platform_features skx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_SKX, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, @@ -614,7 +614,7 @@ static const struct platform_features icx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_ICX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -627,7 +627,7 @@ static const struct platform_features spr_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_SKX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -668,7 +668,7 @@ static const struct platform_features gmt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -679,7 +679,7 @@ static const struct platform_features gmtd_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 25000000, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, @@ -690,7 +690,7 @@ static const struct platform_features gmtp_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -700,7 +700,7 @@ static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -711,7 +711,7 @@ static const struct platform_features tmtd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL, @@ -5829,12 +5829,7 @@ void process_cpuid() probe_bclk(); do_snb_cstates = has_snb_msrs(family, model); - if (do_snb_cstates) - BIC_PRESENT(BIC_CPU_c7); - do_irtl_snb = has_snb_msrs(family, model); - if (do_snb_cstates && (pkg_cstate_limit >= PCL__2)) - BIC_PRESENT(BIC_Pkgpc2); if (pkg_cstate_limit >= PCL__3) BIC_PRESENT(BIC_Pkgpc3); if (pkg_cstate_limit >= PCL__6) -- cgit v1.2.3 From 6f1935c036f79b56b6a1dc6e51c8c6fe483983ec Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 8 Sep 2023 23:17:23 +0800 Subject: tools/power/turbostat: Adjust cstate for models with .cst_limit set Enable PC3/PC6 for platforms with .cst_limit set because package cstates are guarded by pkg_cstate_limit. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 58 ++++++++++++++++------------------- 1 file changed, 27 insertions(+), 31 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 174a8d0750da..2bfbf4ccf5ac 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -416,7 +416,7 @@ static const struct platform_features nhm_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_NHM, .trl_msrs = TRL_BASE, }; @@ -425,7 +425,7 @@ static const struct platform_features nhx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_NHM, }; @@ -434,7 +434,7 @@ static const struct platform_features snb_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -445,7 +445,7 @@ static const struct platform_features snx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, @@ -457,7 +457,7 @@ static const struct platform_features ivb_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -468,7 +468,7 @@ static const struct platform_features ivx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE | TRL_LIMIT1, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, @@ -480,7 +480,7 @@ static const struct platform_features hsw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -493,7 +493,7 @@ static const struct platform_features hsx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, .plr_msrs = PLR_CORE | PLR_RING, @@ -507,7 +507,7 @@ static const struct platform_features hswl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -520,7 +520,7 @@ static const struct platform_features hswg_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -533,7 +533,7 @@ static const struct platform_features bdw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -545,7 +545,7 @@ static const struct platform_features bdwg_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -557,7 +557,7 @@ static const struct platform_features bdx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, @@ -572,7 +572,7 @@ static const struct platform_features skl_features = { .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 24000000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -586,7 +586,7 @@ static const struct platform_features cnl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -600,7 +600,7 @@ static const struct platform_features skx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_SKX, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, @@ -614,7 +614,7 @@ static const struct platform_features icx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_ICX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -627,7 +627,7 @@ static const struct platform_features spr_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_SKX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -636,7 +636,7 @@ static const struct platform_features spr_features = { static const struct platform_features slv_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, @@ -648,7 +648,7 @@ static const struct platform_features slvd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE, @@ -658,7 +658,7 @@ static const struct platform_features slvd_features = { static const struct platform_features amt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_133MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_AMT, .trl_msrs = TRL_BASE, }; @@ -668,7 +668,7 @@ static const struct platform_features gmt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -679,7 +679,7 @@ static const struct platform_features gmtd_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 25000000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, @@ -690,7 +690,7 @@ static const struct platform_features gmtp_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -700,7 +700,7 @@ static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -711,7 +711,7 @@ static const struct platform_features tmtd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL, @@ -722,7 +722,7 @@ static const struct platform_features knl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6, + .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_KNL, .trl_msrs = TRL_KNL, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -5830,10 +5830,6 @@ void process_cpuid() do_snb_cstates = has_snb_msrs(family, model); do_irtl_snb = has_snb_msrs(family, model); - if (pkg_cstate_limit >= PCL__3) - BIC_PRESENT(BIC_Pkgpc3); - if (pkg_cstate_limit >= PCL__6) - BIC_PRESENT(BIC_Pkgpc6); if (do_snb_cstates && (pkg_cstate_limit >= PCL__7)) BIC_PRESENT(BIC_Pkgpc7); if (has_slv_msrs(family, model)) { -- cgit v1.2.3 From 192cbf0468ae31062526287e257f5b56214d2da5 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 8 Sep 2023 23:17:58 +0800 Subject: tools/power/turbostat: Adjust cstate for has_snb_msrs() models Enable PC7 for has_snb_msrs() models. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 46 ++++++++++++++++------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 2bfbf4ccf5ac..f3d44e81d7d5 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -221,7 +221,6 @@ unsigned int rapl_joules; unsigned int summary_only; unsigned int list_header_only; unsigned int dump_only; -unsigned int do_snb_cstates; unsigned int do_knl_cstates; unsigned int do_slm_cstates; unsigned int use_c1_residency_msr; @@ -434,7 +433,7 @@ static const struct platform_features snb_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -445,7 +444,7 @@ static const struct platform_features snx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, @@ -457,7 +456,7 @@ static const struct platform_features ivb_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -468,7 +467,7 @@ static const struct platform_features ivx_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SNB, .trl_msrs = TRL_BASE | TRL_LIMIT1, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, @@ -480,7 +479,7 @@ static const struct platform_features hsw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -493,7 +492,7 @@ static const struct platform_features hsx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, .plr_msrs = PLR_CORE | PLR_RING, @@ -507,7 +506,7 @@ static const struct platform_features hswl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -520,7 +519,7 @@ static const struct platform_features hswg_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -533,7 +532,7 @@ static const struct platform_features bdw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -545,7 +544,7 @@ static const struct platform_features bdwg_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -557,7 +556,7 @@ static const struct platform_features bdx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, @@ -572,7 +571,7 @@ static const struct platform_features skl_features = { .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 24000000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -586,7 +585,7 @@ static const struct platform_features cnl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -600,7 +599,7 @@ static const struct platform_features skx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SKX, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, @@ -614,7 +613,7 @@ static const struct platform_features icx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_ICX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -627,7 +626,7 @@ static const struct platform_features spr_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SKX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -668,7 +667,7 @@ static const struct platform_features gmt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -679,7 +678,7 @@ static const struct platform_features gmtd_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 25000000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, @@ -690,7 +689,7 @@ static const struct platform_features gmtp_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -700,7 +699,7 @@ static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -711,7 +710,7 @@ static const struct platform_features tmtd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL, @@ -5827,11 +5826,8 @@ void process_cpuid() if (platform->has_nhm_msrs) BIC_PRESENT(BIC_SMI); probe_bclk(); - do_snb_cstates = has_snb_msrs(family, model); do_irtl_snb = has_snb_msrs(family, model); - if (do_snb_cstates && (pkg_cstate_limit >= PCL__7)) - BIC_PRESENT(BIC_Pkgpc7); if (has_slv_msrs(family, model)) { BIC_NOT_PRESENT(BIC_Pkgpc2); BIC_NOT_PRESENT(BIC_Pkgpc3); -- cgit v1.2.3 From ff206149551f09117f44883650a45ae692745703 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:07:08 +0800 Subject: tools/power/turbostat: Adjust cstate for has_slv_msrs() models Disable PC2/PC3/PC7 and enable PC6 for has_slv_msrs() models. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index f3d44e81d7d5..972f5a9b14e6 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -635,7 +635,7 @@ static const struct platform_features spr_features = { static const struct platform_features slv_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, - .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, + .supported_cstates = CC1 | CC3 | CC6 | PC6, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, @@ -5829,10 +5829,6 @@ void process_cpuid() do_irtl_snb = has_snb_msrs(family, model); if (has_slv_msrs(family, model)) { - BIC_NOT_PRESENT(BIC_Pkgpc2); - BIC_NOT_PRESENT(BIC_Pkgpc3); - BIC_PRESENT(BIC_Pkgpc6); - BIC_NOT_PRESENT(BIC_Pkgpc7); BIC_PRESENT(BIC_Mod_c6); use_c1_residency_msr = 1; } -- cgit v1.2.3 From 3d982ac0dafeab860b9d42f5cc41a78753275fdd Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:09:20 +0800 Subject: tools/power/turbostat: Adjust cstate for is_jvl() models Disable CC3/CC7/PC2/PC3/PC6/PC7 for is_jvl() models. Delete is_jvl() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 972f5a9b14e6..e95972edde3c 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -710,7 +710,7 @@ static const struct platform_features tmtd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL, @@ -4361,21 +4361,6 @@ int is_ehl(unsigned int family, unsigned int model) return 0; } -int is_jvl(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_ATOM_TREMONT_D: - return 1; - } - return 0; -} - static void remove_underbar(char *s) { char *to = s; @@ -5832,14 +5817,6 @@ void process_cpuid() BIC_PRESENT(BIC_Mod_c6); use_c1_residency_msr = 1; } - if (is_jvl(family, model)) { - BIC_NOT_PRESENT(BIC_CPU_c3); - BIC_NOT_PRESENT(BIC_CPU_c7); - BIC_NOT_PRESENT(BIC_Pkgpc2); - BIC_NOT_PRESENT(BIC_Pkgpc3); - BIC_NOT_PRESENT(BIC_Pkgpc6); - BIC_NOT_PRESENT(BIC_Pkgpc7); - } if (is_dnv(family, model)) { BIC_PRESENT(BIC_CPU_c1); BIC_NOT_PRESENT(BIC_CPU_c3); -- cgit v1.2.3 From 8e20ced057423f0edaf40b650facc221e8030b33 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:12:29 +0800 Subject: tools/power/turbostat: Adjust cstate for is_dnv() models Enable CC1 and disable CC3/CC7/PC3/PC7 for is_dnv() models. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index e95972edde3c..069704ef3c80 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -678,7 +678,7 @@ static const struct platform_features gmtd_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 25000000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, @@ -5818,11 +5818,6 @@ void process_cpuid() use_c1_residency_msr = 1; } if (is_dnv(family, model)) { - BIC_PRESENT(BIC_CPU_c1); - BIC_NOT_PRESENT(BIC_CPU_c3); - BIC_NOT_PRESENT(BIC_Pkgpc3); - BIC_NOT_PRESENT(BIC_CPU_c7); - BIC_NOT_PRESENT(BIC_Pkgpc7); use_c1_residency_msr = 1; } if (is_skx(family, model) || is_icx(family, model) || is_spr(family, model)) { -- cgit v1.2.3 From 24d16bec379db6eea2d72e18c97c6c80e486a5e1 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 8 Sep 2023 23:18:27 +0800 Subject: tools/power/turbostat: Adjust cstate for is_skx()/is_icx()/is_spr() models Disable CC3/CC7/PC3/PC7 for is_skx()/is_icx()/is_spr() models. Delete is_skx() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 069704ef3c80..262af40fe35d 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -599,7 +599,7 @@ static const struct platform_features skx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_SKX, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, @@ -613,7 +613,7 @@ static const struct platform_features icx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_ICX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -626,7 +626,7 @@ static const struct platform_features spr_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_SKX, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -4298,22 +4298,6 @@ int is_bdx(unsigned int family, unsigned int model) return 0; } -int is_skx(unsigned int family, unsigned int model) -{ - - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_SKYLAKE_X: - return 1; - } - return 0; -} - int is_icx(unsigned int family, unsigned int model) { @@ -5820,12 +5804,6 @@ void process_cpuid() if (is_dnv(family, model)) { use_c1_residency_msr = 1; } - if (is_skx(family, model) || is_icx(family, model) || is_spr(family, model)) { - BIC_NOT_PRESENT(BIC_CPU_c3); - BIC_NOT_PRESENT(BIC_Pkgpc3); - BIC_NOT_PRESENT(BIC_CPU_c7); - BIC_NOT_PRESENT(BIC_Pkgpc7); - } if (is_bdx(family, model)) { BIC_NOT_PRESENT(BIC_CPU_c7); BIC_NOT_PRESENT(BIC_Pkgpc7); -- cgit v1.2.3 From 1109694817fb4fcdfccb1a86fd58e69fb60f4eab Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:16:52 +0800 Subject: tools/power/turbostat: Adjust cstate for is_bdx() models Disable CC7/PC7 for is_bdx() models. Delete is_bdx() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 262af40fe35d..27ca29f0545a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -556,7 +556,7 @@ static const struct platform_features bdx_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC3 | CC6 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, @@ -4282,22 +4282,6 @@ int is_dnv(unsigned int family, unsigned int model) return 0; } -int is_bdx(unsigned int family, unsigned int model) -{ - - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_BROADWELL_X: - return 1; - } - return 0; -} - int is_icx(unsigned int family, unsigned int model) { @@ -5804,10 +5788,6 @@ void process_cpuid() if (is_dnv(family, model)) { use_c1_residency_msr = 1; } - if (is_bdx(family, model)) { - BIC_NOT_PRESENT(BIC_CPU_c7); - BIC_NOT_PRESENT(BIC_Pkgpc7); - } if (has_c8910_msrs(family, model)) { if (pkg_cstate_limit >= PCL__8) BIC_PRESENT(BIC_Pkgpc8); -- cgit v1.2.3 From 4d2c95d40a90877ffd8f961055419f1f550a7ed9 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:20:02 +0800 Subject: tools/power/turbostat: Adjust cstate for has_c8910_msrs() models Enable PC8/PC9/PC10 for has_c8910_msrs() models. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 27ca29f0545a..b0bc973c077d 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -506,7 +506,7 @@ static const struct platform_features hswl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, @@ -532,7 +532,7 @@ static const struct platform_features bdw_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -571,7 +571,7 @@ static const struct platform_features skl_features = { .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 24000000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -585,7 +585,7 @@ static const struct platform_features cnl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -667,7 +667,7 @@ static const struct platform_features gmt_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -689,7 +689,7 @@ static const struct platform_features gmtp_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, .crystal_freq = 19200000, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, @@ -699,7 +699,7 @@ static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, + .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -5788,14 +5788,6 @@ void process_cpuid() if (is_dnv(family, model)) { use_c1_residency_msr = 1; } - if (has_c8910_msrs(family, model)) { - if (pkg_cstate_limit >= PCL__8) - BIC_PRESENT(BIC_Pkgpc8); - if (pkg_cstate_limit >= PCL__9) - BIC_PRESENT(BIC_Pkgpc9); - if (pkg_cstate_limit >= PCL_10) - BIC_PRESENT(BIC_Pkgpc10); - } do_irtl_hsw = has_c8910_msrs(family, model); if (has_skl_msrs(family, model)) { BIC_PRESENT(BIC_Totl_c0); -- cgit v1.2.3 From cd7a2b6a61100a0fe8a40916d1afbd72d8833d57 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:24:19 +0800 Subject: tools/power/turbostat: Adjust cstate for is_slm()/is_knl()/is_cnl()/is_ehl() models Disable CC3 for is_slm()/is_knl()/is_cnl()/is_ehl() models. Delete is_cnl()/is_ehl() CPU model checks. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 44 ++++------------------------------- 1 file changed, 5 insertions(+), 39 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index b0bc973c077d..24f470883ca2 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -585,7 +585,7 @@ static const struct platform_features cnl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, + .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, @@ -635,7 +635,7 @@ static const struct platform_features spr_features = { static const struct platform_features slv_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, - .supported_cstates = CC1 | CC3 | CC6 | PC6, + .supported_cstates = CC1 | CC6 | PC6, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, @@ -647,7 +647,7 @@ static const struct platform_features slvd_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, - .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, + .supported_cstates = CC1 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_SLV, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE, @@ -699,7 +699,7 @@ static const struct platform_features tmt_features = { .has_msr_misc_pwr_mgmt = 1, .has_nhm_msrs = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, + .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_GMT, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -721,7 +721,7 @@ static const struct platform_features knl_features = { .has_nhm_msrs = 1, .has_config_tdp = 1, .bclk_freq = BCLK_100MHZ, - .supported_cstates = CC1 | CC3 | CC6 | PC3 | PC6, + .supported_cstates = CC1 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_KNL, .trl_msrs = TRL_KNL, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -4314,21 +4314,6 @@ int is_spr(unsigned int family, unsigned int model) return 0; } -int is_ehl(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_ATOM_TREMONT: - return 1; - } - return 0; -} - static void remove_underbar(char *s) { char *to = s; @@ -5248,22 +5233,6 @@ int is_knl(unsigned int family, unsigned int model) return 0; } -int is_cnl(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - return 1; - } - - return 0; -} - unsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model) { if (is_knl(family, model)) @@ -5798,9 +5767,6 @@ void process_cpuid() do_slm_cstates = is_slm(family, model); do_knl_cstates = is_knl(family, model); - if (do_slm_cstates || do_knl_cstates || is_cnl(family, model) || is_ehl(family, model)) - BIC_NOT_PRESENT(BIC_CPU_c3); - if (!quiet) decode_misc_pwr_mgmt_msr(); -- cgit v1.2.3 From 8c382f9e74663072805565036026d4e79de96425 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:27:26 +0800 Subject: tools/power/turbostat: Use fine grained IRTL output It is pointless to dump the IRTL register for a package cstate that is not supported by the platform. Print IRTL only for states that are available in platform->supported_cstates. Delete has_c8910_msrs() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 99 +++++++++++++---------------------- 1 file changed, 36 insertions(+), 63 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 24f470883ca2..680373010b01 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -229,7 +229,6 @@ unsigned int has_epb; unsigned int has_turbo; unsigned int is_hybrid; unsigned int do_irtl_snb; -unsigned int do_irtl_hsw; unsigned int units = 1000000; /* MHz etc */ unsigned int genuine_intel; unsigned int authentic_amd; @@ -3269,39 +3268,47 @@ void print_irtl(void) { unsigned long long msr; - get_msr(base_cpu, MSR_PKGC3_IRTL, &msr); - fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr); - fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", - (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); - - get_msr(base_cpu, MSR_PKGC6_IRTL, &msr); - fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr); - fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", - (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); - - get_msr(base_cpu, MSR_PKGC7_IRTL, &msr); - fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr); - fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", - (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + if (platform->supported_cstates & PC3) { + get_msr(base_cpu, MSR_PKGC3_IRTL, &msr); + fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr); + fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", + (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + } - if (!do_irtl_hsw) - return; + if (platform->supported_cstates & PC6) { + get_msr(base_cpu, MSR_PKGC6_IRTL, &msr); + fprintf(outf, "cpu%d: MSR_PKGC6_IRTL: 0x%08llx (", base_cpu, msr); + fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", + (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + } - get_msr(base_cpu, MSR_PKGC8_IRTL, &msr); - fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr); - fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", - (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + if (platform->supported_cstates & PC7) { + get_msr(base_cpu, MSR_PKGC7_IRTL, &msr); + fprintf(outf, "cpu%d: MSR_PKGC7_IRTL: 0x%08llx (", base_cpu, msr); + fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", + (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + } - get_msr(base_cpu, MSR_PKGC9_IRTL, &msr); - fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr); - fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", - (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + if (platform->supported_cstates & PC8) { + get_msr(base_cpu, MSR_PKGC8_IRTL, &msr); + fprintf(outf, "cpu%d: MSR_PKGC8_IRTL: 0x%08llx (", base_cpu, msr); + fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", + (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + } - get_msr(base_cpu, MSR_PKGC10_IRTL, &msr); - fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr); - fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", - (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + if (platform->supported_cstates & PC9) { + get_msr(base_cpu, MSR_PKGC9_IRTL, &msr); + fprintf(outf, "cpu%d: MSR_PKGC9_IRTL: 0x%08llx (", base_cpu, msr); + fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", + (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + } + if (platform->supported_cstates & PC10) { + get_msr(base_cpu, MSR_PKGC10_IRTL, &msr); + fprintf(outf, "cpu%d: MSR_PKGC10_IRTL: 0x%08llx (", base_cpu, msr); + fprintf(outf, "%svalid, %lld ns)\n", msr & (1 << 15) ? "" : "NOT", + (msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]); + } } void free_fd_percpu(void) @@ -5145,39 +5152,6 @@ int has_snb_msrs(unsigned int family, unsigned int model) return 0; } -/* - * HSW ULT added support for C8/C9/C10 MSRs: - * - * MSR_PKG_C8_RESIDENCY 0x00000630 - * MSR_PKG_C9_RESIDENCY 0x00000631 - * MSR_PKG_C10_RESIDENCY 0x00000632 - * - * MSR_PKGC8_IRTL 0x00000633 - * MSR_PKGC9_IRTL 0x00000634 - * MSR_PKGC10_IRTL 0x00000635 - * - */ -int has_c8910_msrs(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_HASWELL_L: /* HSW */ - case INTEL_FAM6_BROADWELL: /* BDW */ - case INTEL_FAM6_SKYLAKE_L: /* SKL */ - case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GOLDMONT_PLUS: - case INTEL_FAM6_ATOM_TREMONT: /* EHL */ - return 1; - } - return 0; -} - /* * SKL adds support for additional MSRS: * @@ -5757,7 +5731,6 @@ void process_cpuid() if (is_dnv(family, model)) { use_c1_residency_msr = 1; } - do_irtl_hsw = has_c8910_msrs(family, model); if (has_skl_msrs(family, model)) { BIC_PRESENT(BIC_Totl_c0); BIC_PRESENT(BIC_Any_c0); -- cgit v1.2.3 From 148df4fd04a98fb24198ecb4419c87e07d38af30 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 8 Sep 2023 23:18:51 +0800 Subject: tools/power/turbostat: Abstract IRTL support Abstract the support for MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL. Delete has_snb_msrs() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 72 +++++++++++++---------------------- 1 file changed, 26 insertions(+), 46 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 680373010b01..44be06b763b2 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -228,7 +228,6 @@ unsigned int has_aperf; unsigned int has_epb; unsigned int has_turbo; unsigned int is_hybrid; -unsigned int do_irtl_snb; unsigned int units = 1000000; /* MHz etc */ unsigned int genuine_intel; unsigned int authentic_amd; @@ -284,6 +283,7 @@ struct platform_features { int supported_cstates; /* Core cstates and Package cstates supported */ int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */ + bool has_irtl_msrs; /* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ @@ -434,6 +434,7 @@ static const struct platform_features snb_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SNB, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; @@ -445,6 +446,7 @@ static const struct platform_features snx_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SNB, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, }; @@ -457,6 +459,7 @@ static const struct platform_features ivb_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SNB, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; @@ -468,6 +471,7 @@ static const struct platform_features ivx_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_SNB, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE | TRL_LIMIT1, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM_ALL, }; @@ -480,6 +484,7 @@ static const struct platform_features hsw_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -493,6 +498,7 @@ static const struct platform_features hsx_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE | TRL_LIMIT1 | TRL_LIMIT2, .plr_msrs = PLR_CORE | PLR_RING, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -507,6 +513,7 @@ static const struct platform_features hswl_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -520,6 +527,7 @@ static const struct platform_features hswg_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .plr_msrs = PLR_CORE | PLR_GFX | PLR_RING, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, @@ -533,6 +541,7 @@ static const struct platform_features bdw_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; @@ -545,6 +554,7 @@ static const struct platform_features bdwg_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE_ALL | RAPL_GFX | RAPL_PKG_POWER_INFO, }; @@ -557,6 +567,7 @@ static const struct platform_features bdx_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC3 | CC6 | PC2 | PC3 | PC6, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -572,6 +583,7 @@ static const struct platform_features skl_features = { .crystal_freq = 24000000, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -586,6 +598,7 @@ static const struct platform_features cnl_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -600,6 +613,7 @@ static const struct platform_features skx_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_SKX, + .has_irtl_msrs = 1, .has_cst_auto_convension = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, @@ -614,6 +628,7 @@ static const struct platform_features icx_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_ICX, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, .has_fixed_rapl_unit = 1, @@ -627,6 +642,7 @@ static const struct platform_features spr_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_SKX, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; @@ -668,6 +684,7 @@ static const struct platform_features gmt_features = { .crystal_freq = 19200000, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_GMT, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, }; @@ -679,6 +696,7 @@ static const struct platform_features gmtd_features = { .crystal_freq = 25000000, .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_GMT, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, }; @@ -690,6 +708,7 @@ static const struct platform_features gmtp_features = { .crystal_freq = 19200000, .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_GMT, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_PKG_POWER_INFO, }; @@ -700,6 +719,7 @@ static const struct platform_features tmt_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_GMT, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, .enable_tsc_tweak = 1, @@ -711,6 +731,7 @@ static const struct platform_features tmtd_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6, .cst_limit = CST_LIMIT_GMT, + .has_irtl_msrs = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL, }; @@ -3268,6 +3289,9 @@ void print_irtl(void) { unsigned long long msr; + if (!platform->has_irtl_msrs) + return; + if (platform->supported_cstates & PC3) { get_msr(base_cpu, MSR_PKGC3_IRTL, &msr); fprintf(outf, "cpu%d: MSR_PKGC3_IRTL: 0x%08llx (", base_cpu, msr); @@ -5109,49 +5133,6 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) return 0; } -/* - * SNB adds support for additional MSRs: - * - * MSR_PKG_C7_RESIDENCY 0x000003fa - * MSR_CORE_C7_RESIDENCY 0x000003fe - * MSR_PKG_C2_RESIDENCY 0x0000060d - */ - -int has_snb_msrs(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_SANDYBRIDGE: - case INTEL_FAM6_SANDYBRIDGE_X: - case INTEL_FAM6_IVYBRIDGE: /* IVB */ - case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */ - case INTEL_FAM6_HASWELL: /* HSW */ - case INTEL_FAM6_HASWELL_X: /* HSW */ - case INTEL_FAM6_HASWELL_L: /* HSW */ - case INTEL_FAM6_HASWELL_G: /* HSW */ - case INTEL_FAM6_BROADWELL: /* BDW */ - case INTEL_FAM6_BROADWELL_G: /* BDW */ - case INTEL_FAM6_BROADWELL_X: /* BDX */ - case INTEL_FAM6_SKYLAKE_L: /* SKL */ - case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - case INTEL_FAM6_SKYLAKE_X: /* SKX */ - case INTEL_FAM6_ICELAKE_X: /* ICX */ - case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ - case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ - case INTEL_FAM6_ATOM_GOLDMONT_PLUS: - case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ - case INTEL_FAM6_ATOM_TREMONT: /* EHL */ - case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */ - return 1; - } - return 0; -} - /* * SKL adds support for additional MSRS: * @@ -5723,7 +5704,6 @@ void process_cpuid() BIC_PRESENT(BIC_SMI); probe_bclk(); - do_irtl_snb = has_snb_msrs(family, model); if (has_slv_msrs(family, model)) { BIC_PRESENT(BIC_Mod_c6); use_c1_residency_msr = 1; @@ -6098,7 +6078,7 @@ void turbostat_init() if (!quiet) for_all_cpus(print_thermal, ODD_COUNTERS); - if (!quiet && do_irtl_snb) + if (!quiet) print_irtl(); if (DO_BIC(BIC_IPC)) -- cgit v1.2.3 From 76d83d2ae8e3099d9a6bd67fba918108824d7d4d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:41:30 +0800 Subject: tools/power/turbostat: Abstract MSR_CORE_C1_RES support Abstract the support for MSR_CORE_C1_RES. Delete is_dnv() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 44be06b763b2..de9260c96678 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -223,7 +223,6 @@ unsigned int list_header_only; unsigned int dump_only; unsigned int do_knl_cstates; unsigned int do_slm_cstates; -unsigned int use_c1_residency_msr; unsigned int has_aperf; unsigned int has_epb; unsigned int has_turbo; @@ -284,6 +283,7 @@ struct platform_features { int cst_limit; /* MSR_PKG_CST_CONFIG_CONTROL */ bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */ bool has_irtl_msrs; /* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */ + bool has_msr_core_c1_res; /* MSR_CORE_C1_RES */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ @@ -652,6 +652,7 @@ static const struct platform_features slv_features = { .bclk_freq = BCLK_SLV, .supported_cstates = CC1 | CC6 | PC6, .cst_limit = CST_LIMIT_SLV, + .has_msr_core_c1_res = 1, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, .has_rapl_divisor = 1, @@ -697,6 +698,7 @@ static const struct platform_features gmtd_features = { .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_GMT, .has_irtl_msrs = 1, + .has_msr_core_c1_res = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_CORE_ENERGY_STATUS, }; @@ -2069,7 +2071,7 @@ void delta_core(struct core_data *new, struct core_data *old) int soft_c1_residency_display(int bic) { - if (!DO_BIC(BIC_CPU_c1) || use_c1_residency_msr) + if (!DO_BIC(BIC_CPU_c1) || platform->has_msr_core_c1_res) return 0; return DO_BIC_READ(bic); @@ -2118,7 +2120,7 @@ int delta_thread(struct thread_data *new, struct thread_data *old, struct core_d } } - if (use_c1_residency_msr) { + if (platform->has_msr_core_c1_res) { /* * Some models have a dedicated C1 residency MSR, * which should be more accurate than the derivation below. @@ -2700,7 +2702,7 @@ retry: return -5; t->smi_count = msr & 0xFFFFFFFF; } - if (DO_BIC(BIC_CPU_c1) && use_c1_residency_msr) { + if (DO_BIC(BIC_CPU_c1) && platform->has_msr_core_c1_res) { if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1)) return -6; } @@ -4297,22 +4299,6 @@ int has_slv_msrs(unsigned int family, unsigned int model) return 0; } -int is_dnv(unsigned int family, unsigned int model) -{ - - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_ATOM_GOLDMONT_D: - return 1; - } - return 0; -} - int is_icx(unsigned int family, unsigned int model) { @@ -5706,10 +5692,6 @@ void process_cpuid() if (has_slv_msrs(family, model)) { BIC_PRESENT(BIC_Mod_c6); - use_c1_residency_msr = 1; - } - if (is_dnv(family, model)) { - use_c1_residency_msr = 1; } if (has_skl_msrs(family, model)) { BIC_PRESENT(BIC_Totl_c0); -- cgit v1.2.3 From 9cc1c1038526a5b6c9a57397def80ba79c260ff2 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:47:30 +0800 Subject: tools/power/turbostat: Abstract MSR_MODULE_C6_RES_MS support Abstract MSR_MODULE_C6_RES_MS support. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index de9260c96678..5f90d96bd9e3 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -284,6 +284,7 @@ struct platform_features { bool has_cst_auto_convension; /* AUTOMATIC_CSTATE_CONVERSION bit in MSR_PKG_CST_CONFIG_CONTROL */ bool has_irtl_msrs; /* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */ bool has_msr_core_c1_res; /* MSR_CORE_C1_RES */ + bool has_msr_module_c6_res_ms; /* MSR_MODULE_C6_RES_MS */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ @@ -653,6 +654,7 @@ static const struct platform_features slv_features = { .supported_cstates = CC1 | CC6 | PC6, .cst_limit = CST_LIMIT_SLV, .has_msr_core_c1_res = 1, + .has_msr_module_c6_res_ms = 1, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, .has_rapl_divisor = 1, @@ -5690,9 +5692,9 @@ void process_cpuid() BIC_PRESENT(BIC_SMI); probe_bclk(); - if (has_slv_msrs(family, model)) { + if (platform->has_msr_module_c6_res_ms) BIC_PRESENT(BIC_Mod_c6); - } + if (has_skl_msrs(family, model)) { BIC_PRESENT(BIC_Totl_c0); BIC_PRESENT(BIC_Any_c0); -- cgit v1.2.3 From 6c36882e09dbc9a44d64180ba7972838d3f45488 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 14:52:24 +0800 Subject: tools/power/turbostat: Abstract MSR_CC6/MC6_DEMOTION_POLICY_CONFIG support Abstract the support for MSR_CC6/MC6_DEMOTION_POLICY_CONFIG. Delete has_slv_msrs() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 5f90d96bd9e3..f8d7ba87f968 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -285,6 +285,7 @@ struct platform_features { bool has_irtl_msrs; /* MSR_PKGC3/PKGC6/PKGC7/PKGC8/PKGC9/PKGC10_IRTL */ bool has_msr_core_c1_res; /* MSR_CORE_C1_RES */ bool has_msr_module_c6_res_ms; /* MSR_MODULE_C6_RES_MS */ + bool has_msr_c6_demotion_policy_config; /* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ @@ -655,6 +656,7 @@ static const struct platform_features slv_features = { .cst_limit = CST_LIMIT_SLV, .has_msr_core_c1_res = 1, .has_msr_module_c6_res_ms = 1, + .has_msr_c6_demotion_policy_config = 1, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, .has_rapl_divisor = 1, @@ -4279,28 +4281,6 @@ void probe_bclk(void) tsc_tweak = base_hz / tsc_hz; } -/* - * SLV client has support for unique MSRs: - * - * MSR_CC6_DEMOTION_POLICY_CONFIG - * MSR_MC6_DEMOTION_POLICY_CONFIG - */ - -int has_slv_msrs(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_ATOM_SILVERMONT: - return 1; - } - return 0; -} - int is_icx(unsigned int family, unsigned int model) { @@ -5358,6 +5338,9 @@ void decode_c6_demotion_policy_msr(void) { unsigned long long msr; + if (!platform->has_msr_c6_demotion_policy_config) + return; + if (!get_msr(base_cpu, MSR_CC6_DEMOTION_POLICY_CONFIG, &msr)) fprintf(outf, "cpu%d: MSR_CC6_DEMOTION_POLICY_CONFIG: 0x%08llx (%sable-CC6-Demotion)\n", base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS"); @@ -5707,7 +5690,7 @@ void process_cpuid() if (!quiet) decode_misc_pwr_mgmt_msr(); - if (!quiet && has_slv_msrs(family, model)) + if (!quiet) decode_c6_demotion_policy_msr(); rapl_probe(); -- cgit v1.2.3 From c8202a6c3acf7bbde42b5e389eec40fd8e1b8358 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 15:26:14 +0800 Subject: tools/power/turbostat: Abstract MSR_ATOM_PKG_C6_RESIDENCY support Abstract the support for MSR_ATOM_PKG_C6_RESIDENCY. Delete is_slm() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index f8d7ba87f968..a04861846d33 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -222,7 +222,6 @@ unsigned int summary_only; unsigned int list_header_only; unsigned int dump_only; unsigned int do_knl_cstates; -unsigned int do_slm_cstates; unsigned int has_aperf; unsigned int has_epb; unsigned int has_turbo; @@ -286,6 +285,7 @@ struct platform_features { bool has_msr_core_c1_res; /* MSR_CORE_C1_RES */ bool has_msr_module_c6_res_ms; /* MSR_MODULE_C6_RES_MS */ bool has_msr_c6_demotion_policy_config; /* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */ + bool has_msr_atom_pkg_c6_residency; /* MSR_ATOM_PKG_C6_RESIDENCY */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ @@ -657,6 +657,7 @@ static const struct platform_features slv_features = { .has_msr_core_c1_res = 1, .has_msr_module_c6_res_ms = 1, .has_msr_c6_demotion_policy_config = 1, + .has_msr_atom_pkg_c6_residency = 1, .trl_msrs = TRL_ATOM, .rapl_msrs = RAPL_PKG | RAPL_CORE, .has_rapl_divisor = 1, @@ -669,6 +670,7 @@ static const struct platform_features slvd_features = { .bclk_freq = BCLK_SLV, .supported_cstates = CC1 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_SLV, + .has_msr_atom_pkg_c6_residency = 1, .trl_msrs = TRL_BASE, .rapl_msrs = RAPL_PKG | RAPL_CORE, .rapl_quirk_tdp = 30, @@ -2795,7 +2797,7 @@ retry: if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3)) return -9; if (DO_BIC(BIC_Pkgpc6)) { - if (do_slm_cstates) { + if (platform->has_msr_atom_pkg_c6_residency) { if (get_msr(cpu, MSR_ATOM_PKG_C6_RESIDENCY, &p->pc6)) return -10; } else { @@ -5125,22 +5127,6 @@ int has_skl_msrs(unsigned int family, unsigned int model) return 0; } -int is_slm(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */ - case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */ - return 1; - } - return 0; -} - int is_knl(unsigned int family, unsigned int model) { if (!genuine_intel) @@ -5684,7 +5670,6 @@ void process_cpuid() BIC_PRESENT(BIC_GFX_c0); BIC_PRESENT(BIC_CPUGFX); } - do_slm_cstates = is_slm(family, model); do_knl_cstates = is_knl(family, model); if (!quiet) -- cgit v1.2.3 From 80d132cb45f2cc171395bfaacd74567a183ab160 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 15:00:58 +0800 Subject: tools/power/turbostat: Abstract MSR_KNL_CORE_C6_RESIDENCY support Abstract the support for MSR_KNL_CORE_C6_RESIDENCY. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a04861846d33..f0a99e092fa7 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -221,7 +221,6 @@ unsigned int rapl_joules; unsigned int summary_only; unsigned int list_header_only; unsigned int dump_only; -unsigned int do_knl_cstates; unsigned int has_aperf; unsigned int has_epb; unsigned int has_turbo; @@ -286,6 +285,7 @@ struct platform_features { bool has_msr_module_c6_res_ms; /* MSR_MODULE_C6_RES_MS */ bool has_msr_c6_demotion_policy_config; /* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */ bool has_msr_atom_pkg_c6_residency; /* MSR_ATOM_PKG_C6_RESIDENCY */ + bool has_msr_knl_core_c6_residency; /* MSR_KNL_CORE_C6_RESIDENCY */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ @@ -751,6 +751,7 @@ static const struct platform_features knl_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6 | PC3 | PC6, .cst_limit = CST_LIMIT_KNL, + .has_msr_knl_core_c6_residency = 1, .trl_msrs = TRL_KNL, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, .has_fixed_rapl_unit = 1, @@ -2727,10 +2728,10 @@ retry: return -6; } - if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) { + if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !platform->has_msr_knl_core_c6_residency) { if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6)) return -7; - } else if (do_knl_cstates && soft_c1_residency_display(BIC_CPU_c6)) { + } else if (platform->has_msr_knl_core_c6_residency && soft_c1_residency_display(BIC_CPU_c6)) { if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6)) return -7; } @@ -5670,7 +5671,6 @@ void process_cpuid() BIC_PRESENT(BIC_GFX_c0); BIC_PRESENT(BIC_CPUGFX); } - do_knl_cstates = is_knl(family, model); if (!quiet) decode_misc_pwr_mgmt_msr(); -- cgit v1.2.3 From 58ddb691d8d8a281535406766da4e23e0f011126 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 15:07:43 +0800 Subject: tools/power/turbostat: Abstract extended cstate MSRs support Abstract the support for MSR_PKG_WEIGHTED_CORE_C0_RES, MSR_PKG_ANY_CORE_C0_RES, MSR_PKG_ANY_GFXE_C0_RES and MSR_PKG_BOTH_CORE_GFXE_C0_RES. Delete has_skl_msrs() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index f0a99e092fa7..613b284f2f09 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -286,6 +286,7 @@ struct platform_features { bool has_msr_c6_demotion_policy_config; /* MSR_CC6_DEMOTION_POLICY_CONFIG/MSR_MC6_DEMOTION_POLICY_CONFIG */ bool has_msr_atom_pkg_c6_residency; /* MSR_ATOM_PKG_C6_RESIDENCY */ bool has_msr_knl_core_c6_residency; /* MSR_KNL_CORE_C6_RESIDENCY */ + bool has_ext_cst_msrs; /* MSR_PKG_WEIGHTED_CORE_C0_RES/MSR_PKG_ANY_CORE_C0_RES/MSR_PKG_ANY_GFXE_C0_RES/MSR_PKG_BOTH_CORE_GFXE_C0_RES */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ @@ -586,6 +587,7 @@ static const struct platform_features skl_features = { .supported_cstates = CC1 | CC3 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, .has_irtl_msrs = 1, + .has_ext_cst_msrs = 1, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -601,6 +603,7 @@ static const struct platform_features cnl_features = { .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, .has_irtl_msrs = 1, + .has_ext_cst_msrs = 1, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, @@ -5104,30 +5107,6 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) return 0; } -/* - * SKL adds support for additional MSRS: - * - * MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658 - * MSR_PKG_ANY_CORE_C0_RES 0x00000659 - * MSR_PKG_ANY_GFXE_C0_RES 0x0000065A - * MSR_PKG_BOTH_CORE_GFXE_C0_RES 0x0000065B - */ -int has_skl_msrs(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_SKYLAKE_L: /* SKL */ - case INTEL_FAM6_CANNONLAKE_L: /* CNL */ - return 1; - } - return 0; -} - int is_knl(unsigned int family, unsigned int model) { if (!genuine_intel) @@ -5665,7 +5644,7 @@ void process_cpuid() if (platform->has_msr_module_c6_res_ms) BIC_PRESENT(BIC_Mod_c6); - if (has_skl_msrs(family, model)) { + if (platform->has_ext_cst_msrs) { BIC_PRESENT(BIC_Totl_c0); BIC_PRESENT(BIC_Any_c0); BIC_PRESENT(BIC_GFX_c0); -- cgit v1.2.3 From ed43247b15a4fb4df01c3408fcab6e206f93ab87 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 15:49:10 +0800 Subject: tools/power/turbostat: Abstract aperf/mperf multiplier support Abstract aperf/mperf multiplier support. Delete is_knl() CPU model check. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 613b284f2f09..65a507d82fc4 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -296,6 +296,7 @@ struct platform_features { int rapl_quirk_tdp; /* Hardcoded TDP value when cannot be retrieved from hardware */ int tcc_offset_bits; /* TCC Offset bits in MSR_IA32_TEMPERATURE_TARGET */ bool enable_tsc_tweak; /* Use CPU Base freq instead of TSC freq for aperf/mperf counter */ + bool need_perf_multiplier; /* mperf/aperf multiplier */ }; struct platform_data { @@ -758,6 +759,7 @@ static const struct platform_features knl_features = { .trl_msrs = TRL_KNL, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, .has_fixed_rapl_unit = 1, + .need_perf_multiplier = 1, }; static const struct platform_features default_features = { @@ -5107,28 +5109,6 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) return 0; } -int is_knl(unsigned int family, unsigned int model) -{ - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ - return 1; - } - return 0; -} - -unsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model) -{ - if (is_knl(family, model)) - return 1024; - return 1; -} - int get_cpu_type(struct thread_data *t, struct core_data *c, struct pkg_data *p) { unsigned int eax, ebx, ecx, edx; @@ -5630,7 +5610,7 @@ void process_cpuid() } if (has_aperf) - aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model); + aperf_mperf_multiplier = platform->need_perf_multiplier ? 1024 : 1; BIC_PRESENT(BIC_IRQ); BIC_PRESENT(BIC_TSC_MHz); -- cgit v1.2.3 From 7d0ebe6f7eaf8c0ac069ddab1fe3793401139fb3 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 15:57:44 +0800 Subject: tools/power/turbostat: Abstract cstate prewake bit support Abstract cstate prewake bit support. Delete is_icx()/is_spr() CPU model checks. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 47 +++-------------------------------- 1 file changed, 4 insertions(+), 43 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 65a507d82fc4..580cc2a3b947 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -252,7 +252,6 @@ unsigned int tj_max_override; double rapl_power_units, rapl_time_units; double rapl_dram_energy_units, rapl_energy_units; double rapl_joule_counter_range; -unsigned int dis_cstate_prewake; unsigned int crystal_hz; unsigned long long tsc_hz; int base_cpu; @@ -287,6 +286,7 @@ struct platform_features { bool has_msr_atom_pkg_c6_residency; /* MSR_ATOM_PKG_C6_RESIDENCY */ bool has_msr_knl_core_c6_residency; /* MSR_KNL_CORE_C6_RESIDENCY */ bool has_ext_cst_msrs; /* MSR_PKG_WEIGHTED_CORE_C0_RES/MSR_PKG_ANY_CORE_C0_RES/MSR_PKG_ANY_GFXE_C0_RES/MSR_PKG_BOTH_CORE_GFXE_C0_RES */ + bool has_cst_prewake_bit; /* Cstate prewake bit in MSR_IA32_POWER_CTL */ int trl_msrs; /* MSR_TURBO_RATIO_LIMIT/LIMIT1/LIMIT2/SECONDARY, Atom TRL MSRs */ int plr_msrs; /* MSR_CORE/GFX/RING_PERF_LIMIT_REASONS */ int rapl_msrs; /* RAPL PKG/DRAM/CORE/GFX MSRs, AMD RAPL MSRs */ @@ -635,6 +635,7 @@ static const struct platform_features icx_features = { .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_ICX, .has_irtl_msrs = 1, + .has_cst_prewake_bit = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, .has_fixed_rapl_unit = 1, @@ -649,6 +650,7 @@ static const struct platform_features spr_features = { .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_SKX, .has_irtl_msrs = 1, + .has_cst_prewake_bit = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; @@ -3014,8 +3016,6 @@ void probe_cst_limit(void) pkg_cstate_limit = pkg_cstate_limits[msr & 0xF]; } -void prewake_cstate_probe(unsigned int family, unsigned int model); - static void dump_platform_info(void) { unsigned long long msr; @@ -3036,7 +3036,7 @@ static void dump_platform_info(void) base_cpu, msr, msr & 0x2 ? "EN" : "DIS"); /* C-state Pre-wake Disable (CSTATE_PREWAKE_DISABLE) */ - if (dis_cstate_prewake) + if (platform->has_cst_prewake_bit) fprintf(outf, "C-state Pre-wake: %sabled\n", msr & 0x40000000 ? "DIS" : "EN"); return; @@ -4289,38 +4289,6 @@ void probe_bclk(void) tsc_tweak = base_hz / tsc_hz; } -int is_icx(unsigned int family, unsigned int model) -{ - - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_ICELAKE_X: - return 1; - } - return 0; -} - -int is_spr(unsigned int family, unsigned int model) -{ - - if (!genuine_intel) - return 0; - - if (family != 6) - return 0; - - switch (model) { - case INTEL_FAM6_SAPPHIRERAPIDS_X: - return 1; - } - return 0; -} - static void remove_underbar(char *s) { char *to = s; @@ -4910,12 +4878,6 @@ void rapl_probe(void) rapl_probe_amd(); } -void prewake_cstate_probe(unsigned int family, unsigned int model) -{ - if (is_icx(family, model) || is_spr(family, model)) - dis_cstate_prewake = 1; -} - int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p) { unsigned long long msr; @@ -5638,7 +5600,6 @@ void process_cpuid() decode_c6_demotion_policy_msr(); rapl_probe(); - prewake_cstate_probe(family, model); if (!quiet) dump_cstate_pstate_config_info(); -- cgit v1.2.3 From d085b3b0f11af7d23601b832e0d9e446d18df968 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 21:53:21 +0800 Subject: tools/power/turbostat: Delete intel_model_duplicates() Now CPU model checks have been cleaned up, no code depends on the duplicated CPU model value. Delete intel_model_duplicates(). Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 59 ----------------------------------- 1 file changed, 59 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 580cc2a3b947..89f53e1ac63a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5258,63 +5258,6 @@ void decode_c6_demotion_policy_msr(void) base_cpu, msr, msr & (1 << 0) ? "EN" : "DIS"); } -/* - * When models are the same, for the purpose of turbostat, reuse - */ -unsigned int intel_model_duplicates(unsigned int model) -{ - - switch (model) { - case INTEL_FAM6_NEHALEM_EP: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */ - case INTEL_FAM6_NEHALEM_G: /* Core i7 and i5 Processor - Nehalem */ - case INTEL_FAM6_WESTMERE: /* Westmere Client - Clarkdale, Arrandale */ - case INTEL_FAM6_WESTMERE_EP: /* Westmere EP - Gulftown */ - return INTEL_FAM6_NEHALEM; - - case INTEL_FAM6_WESTMERE_EX: /* Westmere-EX Xeon - Eagleton */ - return INTEL_FAM6_NEHALEM_EX; - - case INTEL_FAM6_XEON_PHI_KNM: - return INTEL_FAM6_XEON_PHI_KNL; - - case INTEL_FAM6_BROADWELL_D: /* BDX-DE */ - return INTEL_FAM6_BROADWELL_X; - - case INTEL_FAM6_SKYLAKE: - case INTEL_FAM6_KABYLAKE_L: - case INTEL_FAM6_KABYLAKE: - case INTEL_FAM6_COMETLAKE_L: - case INTEL_FAM6_COMETLAKE: - return INTEL_FAM6_SKYLAKE_L; - - case INTEL_FAM6_ICELAKE_L: - case INTEL_FAM6_ICELAKE_NNPI: - case INTEL_FAM6_TIGERLAKE_L: - case INTEL_FAM6_TIGERLAKE: - case INTEL_FAM6_ROCKETLAKE: - case INTEL_FAM6_LAKEFIELD: - case INTEL_FAM6_ALDERLAKE: - case INTEL_FAM6_ALDERLAKE_L: - case INTEL_FAM6_ATOM_GRACEMONT: - case INTEL_FAM6_RAPTORLAKE: - case INTEL_FAM6_RAPTORLAKE_P: - case INTEL_FAM6_RAPTORLAKE_S: - case INTEL_FAM6_METEORLAKE: - case INTEL_FAM6_METEORLAKE_L: - return INTEL_FAM6_CANNONLAKE_L; - - case INTEL_FAM6_ATOM_TREMONT_L: - return INTEL_FAM6_ATOM_TREMONT; - - case INTEL_FAM6_ICELAKE_D: - return INTEL_FAM6_ICELAKE_X; - - case INTEL_FAM6_EMERALDRAPIDS_X: - return INTEL_FAM6_SAPPHIRERAPIDS_X; - } - return model; -} - void print_dev_latency(void) { char *path = "/dev/cpu_dma_latency"; @@ -5457,8 +5400,6 @@ void process_cpuid() } probe_platform_features(family, model); - if (genuine_intel) - model = intel_model_duplicates(model); if (!(edx_flags & (1 << 5))) errx(1, "CPUID: no MSR"); -- cgit v1.2.3 From 32e8c6169af7ef7c938b1bd996d27ab171e27d80 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 14:44:06 +0800 Subject: tools/power/turbostat: Improve probe_platform_features() logic AMD/Hygon platforms that don't have RAPL use 'amd_features' to describe the platform features. Unknown Intel platforms use 'default_features' to describe the platform features. As none of the platform feature is set for 'amd_features' or 'default_features', there is no need to maintain both of them. Remove 'amd_features' structure and improve the logic in probe_platform_features(). Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 89f53e1ac63a..102ba515cf4b 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -767,9 +767,6 @@ static const struct platform_features knl_features = { static const struct platform_features default_features = { }; -static const struct platform_features amd_features = { -}; - static const struct platform_features amd_features_with_rapl = { .rapl_msrs = RAPL_AMD_F17H, .has_per_core_rapl = 1, @@ -849,9 +846,9 @@ void probe_platform_features(unsigned int family, unsigned int model) { int i; - if (authentic_amd || hygon_genuine) { - platform = &amd_features; + platform = &default_features; + if (authentic_amd || hygon_genuine) { if (max_extended_level >= 0x80000007) { unsigned int eax, ebx, ecx, edx; @@ -863,8 +860,6 @@ void probe_platform_features(unsigned int family, unsigned int model) return; } - platform = &default_features; - if (!genuine_intel || family != 6) return; -- cgit v1.2.3 From 045acf6064c5567011163e97c28906e0a7791414 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 29 Aug 2023 13:47:58 +0800 Subject: tools/power/turbostat: Relocate cstate probing code Move all cstate probing related code into probe_cstates(). Note that dump_platform_info() actually dumps both MSR_PLATFORM_INFO and MSR_IA32_POWER_CTL. MSR_PLATFORM_INFO is for pstate and MSR_IA32_POWER_CTL is for cstate. So split dump_platform_info() and dump MSR_IA32_POWER_CTL in probe_cstates(). Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 50 ++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 102ba515cf4b..e5ca1586961e 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -272,7 +272,7 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr); struct platform_features { bool has_msr_misc_feature_control; /* MSR_MISC_FEATURE_CONTROL */ bool has_msr_misc_pwr_mgmt; /* MSR_MISC_PWR_MGMT */ - bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, TRL MSRs */ + bool has_nhm_msrs; /* MSR_PLATFORM_INFO, MSR_IA32_TEMPERATURE_TARGET, MSR_SMI_COUNT, MSR_PKG_CST_CONFIG_CONTROL, MSR_IA32_POWER_CTL, TRL MSRs */ bool has_config_tdp; /* MSR_CONFIG_TDP_NOMINAL/LEVEL_1/LEVEL_2/CONTROL, MSR_TURBO_ACTIVATION_RATIO */ int bclk_freq; /* CPU base clock */ int crystal_freq; /* Crystal clock to use when not available from CPUID.15 */ @@ -3025,6 +3025,14 @@ static void dump_platform_info(void) ratio = (msr >> 8) & 0xFF; fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk); +} + +static void dump_power_ctl(void) +{ + unsigned long long msr; + + if (!platform->has_nhm_msrs) + return; get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr); fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n", @@ -3229,6 +3237,9 @@ static void dump_cst_cfg(void) { unsigned long long msr; + if (!platform->has_nhm_msrs) + return; + get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr); fprintf(outf, "cpu%d: MSR_PKG_CST_CONFIG_CONTROL: 0x%08llx", base_cpu, msr); @@ -4332,7 +4343,6 @@ static void dump_cstate_pstate_config_info(void) dump_platform_info(); dump_turbo_ratio_info(); - dump_cst_cfg(); } static int read_sysfs_int(char *path) @@ -5332,6 +5342,25 @@ void probe_cstates(void) if (platform->supported_cstates & PC10 && (pkg_cstate_limit >= PCL_10)) BIC_PRESENT(BIC_Pkgpc10); + + if (platform->has_msr_module_c6_res_ms) + BIC_PRESENT(BIC_Mod_c6); + + if (platform->has_ext_cst_msrs) { + BIC_PRESENT(BIC_Totl_c0); + BIC_PRESENT(BIC_Any_c0); + BIC_PRESENT(BIC_GFX_c0); + BIC_PRESENT(BIC_CPUGFX); + } + + if (quiet) + return; + + dump_power_ctl(); + dump_cst_cfg(); + decode_c6_demotion_policy_msr(); + print_dev_latency(); + dump_sysfs_cstate_config(); } void process_cpuid() @@ -5519,32 +5548,15 @@ void process_cpuid() BIC_PRESENT(BIC_SMI); probe_bclk(); - if (platform->has_msr_module_c6_res_ms) - BIC_PRESENT(BIC_Mod_c6); - - if (platform->has_ext_cst_msrs) { - BIC_PRESENT(BIC_Totl_c0); - BIC_PRESENT(BIC_Any_c0); - BIC_PRESENT(BIC_GFX_c0); - BIC_PRESENT(BIC_CPUGFX); - } - if (!quiet) decode_misc_pwr_mgmt_msr(); - if (!quiet) - decode_c6_demotion_policy_msr(); - rapl_probe(); if (!quiet) dump_cstate_pstate_config_info(); intel_uncore_frequency_probe(); - if (!quiet) - print_dev_latency(); - if (!quiet) - dump_sysfs_cstate_config(); if (!quiet) dump_sysfs_pstate_config(); -- cgit v1.2.3 From 11cd9a09f3e827605cf8fc7c343ddb8c9f4ee95d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 15:58:10 +0800 Subject: tools/power/turbostat: Relocate pstate probing code Introduce probe_pstates() and move all pstate probing related code into it. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 39 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index e5ca1586961e..1bcaee6d0ead 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -3016,6 +3016,9 @@ static void dump_platform_info(void) unsigned long long msr; unsigned int ratio; + if (!platform->has_nhm_msrs) + return; + get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr); @@ -4313,6 +4316,9 @@ static void dump_turbo_ratio_info(void) if (!has_turbo) return; + if (!platform->has_nhm_msrs) + return; + if (platform->trl_msrs & TRL_LIMIT2) dump_turbo_ratio_limit2(); @@ -4336,15 +4342,6 @@ static void dump_turbo_ratio_info(void) dump_config_tdp(); } -static void dump_cstate_pstate_config_info(void) -{ - if (!platform->has_nhm_msrs) - return; - - dump_platform_info(); - dump_turbo_ratio_info(); -} - static int read_sysfs_int(char *path) { FILE *input; @@ -5363,6 +5360,19 @@ void probe_cstates(void) dump_sysfs_cstate_config(); } +void probe_pstates(void) +{ + probe_bclk(); + + if (quiet) + return; + + dump_platform_info(); + dump_turbo_ratio_info(); + dump_sysfs_pstate_config(); + decode_misc_pwr_mgmt_msr(); +} + void process_cpuid() { unsigned int eax, ebx, ecx, edx; @@ -5542,24 +5552,17 @@ void process_cpuid() BIC_PRESENT(BIC_IRQ); BIC_PRESENT(BIC_TSC_MHz); + probe_pstates(); + probe_cstates(); if (platform->has_nhm_msrs) BIC_PRESENT(BIC_SMI); - probe_bclk(); - - if (!quiet) - decode_misc_pwr_mgmt_msr(); rapl_probe(); - if (!quiet) - dump_cstate_pstate_config_info(); intel_uncore_frequency_probe(); - if (!quiet) - dump_sysfs_pstate_config(); - if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) BIC_PRESENT(BIC_GFX_rc6); -- cgit v1.2.3 From 622c8f23556266a5afdd657aa0518b7d70d5dfc7 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 16:00:15 +0800 Subject: tools/power/turbostat: Rename uncore probing function Rename intel_uncore_frequency_probe() to probe_intel_uncore_frequency() to be consistent with other probing function names. Probe uncore frequency right after probing cstates. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 1bcaee6d0ead..a956a30d81de 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4378,7 +4378,7 @@ static void dump_sysfs_file(char *path) fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf); } -static void intel_uncore_frequency_probe(void) +static void probe_intel_uncore_frequency(void) { int i, j; char path[128]; @@ -5556,13 +5556,13 @@ void process_cpuid() probe_cstates(); + probe_intel_uncore_frequency(); + if (platform->has_nhm_msrs) BIC_PRESENT(BIC_SMI); rapl_probe(); - intel_uncore_frequency_probe(); - if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) BIC_PRESENT(BIC_GFX_rc6); -- cgit v1.2.3 From 6cb13609a07ba466b4613fdce7da8c98508069b7 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 16:00:33 +0800 Subject: tools/power/turbostat: Rename rapl probing function Rename rapl_probe() to probe_rapl() to be consistent with other probing function names. Probe rapl after probing uncore frequency. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a956a30d81de..bf2b1d1b2627 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4865,11 +4865,11 @@ void rapl_probe_amd(void) } /* - * rapl_probe() + * probe_rapl() * * sets rapl_power_units, rapl_energy_units, rapl_time_units */ -void rapl_probe(void) +void probe_rapl(void) { if (!platform->rapl_msrs) return; @@ -5558,11 +5558,11 @@ void process_cpuid() probe_intel_uncore_frequency(); + probe_rapl(); + if (platform->has_nhm_msrs) BIC_PRESENT(BIC_SMI); - rapl_probe(); - if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) BIC_PRESENT(BIC_GFX_rc6); -- cgit v1.2.3 From 2538d1673d02f66f6bdf01eebf36e271228778e9 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 16:01:12 +0800 Subject: tools/power/turbostat: Relocate graphics probing code Introduce probe_graphics(), and move all graphics probing related code into it. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index bf2b1d1b2627..feff9ecff368 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4424,6 +4424,20 @@ static void probe_intel_uncore_frequency(void) } } +static void probe_graphics(void) +{ + if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) + BIC_PRESENT(BIC_GFX_rc6); + + if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK) || + !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK)) + BIC_PRESENT(BIC_GFXMHz); + + if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK) || + !access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK)) + BIC_PRESENT(BIC_GFXACTMHz); +} + static void dump_sysfs_cstate_config(void) { char path[64]; @@ -5558,22 +5572,13 @@ void process_cpuid() probe_intel_uncore_frequency(); + probe_graphics(); + probe_rapl(); if (platform->has_nhm_msrs) BIC_PRESENT(BIC_SMI); - if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) - BIC_PRESENT(BIC_GFX_rc6); - - if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK) || - !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK)) - BIC_PRESENT(BIC_GFXMHz); - - if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK) || - !access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK)) - BIC_PRESENT(BIC_GFXACTMHz); - if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK)) BIC_PRESENT(BIC_CPU_LPI); else -- cgit v1.2.3 From e7d7b82de192464b733fb2bcc9e305ea6f6ea47e Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 16:01:36 +0800 Subject: tools/power/turbostat: Relocate lpi probing code Introduce probe_lpi(), and move all lpi probing related code into it. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 38 ++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index feff9ecff368..ad9147757d5a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5374,6 +5374,26 @@ void probe_cstates(void) dump_sysfs_cstate_config(); } +void probe_lpi(void) +{ + if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK)) + BIC_PRESENT(BIC_CPU_LPI); + else + BIC_NOT_PRESENT(BIC_CPU_LPI); + + if (!access(sys_lpi_file_sysfs, R_OK)) { + sys_lpi_file = sys_lpi_file_sysfs; + BIC_PRESENT(BIC_SYS_LPI); + } else if (!access(sys_lpi_file_debugfs, R_OK)) { + sys_lpi_file = sys_lpi_file_debugfs; + BIC_PRESENT(BIC_SYS_LPI); + } else { + sys_lpi_file_sysfs = NULL; + BIC_NOT_PRESENT(BIC_SYS_LPI); + } + +} + void probe_pstates(void) { probe_bclk(); @@ -5570,6 +5590,8 @@ void process_cpuid() probe_cstates(); + probe_lpi(); + probe_intel_uncore_frequency(); probe_graphics(); @@ -5579,27 +5601,11 @@ void process_cpuid() if (platform->has_nhm_msrs) BIC_PRESENT(BIC_SMI); - if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK)) - BIC_PRESENT(BIC_CPU_LPI); - else - BIC_NOT_PRESENT(BIC_CPU_LPI); - if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK)) BIC_PRESENT(BIC_CORE_THROT_CNT); else BIC_NOT_PRESENT(BIC_CORE_THROT_CNT); - if (!access(sys_lpi_file_sysfs, R_OK)) { - sys_lpi_file = sys_lpi_file_sysfs; - BIC_PRESENT(BIC_SYS_LPI); - } else if (!access(sys_lpi_file_debugfs, R_OK)) { - sys_lpi_file = sys_lpi_file_debugfs; - BIC_PRESENT(BIC_SYS_LPI); - } else { - sys_lpi_file_sysfs = NULL; - BIC_NOT_PRESENT(BIC_SYS_LPI); - } - if (!quiet) decode_misc_feature_control(); -- cgit v1.2.3 From db735f8ba78bf7692579b78f0ca1e40563ef79fd Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 31 Aug 2023 16:02:16 +0800 Subject: tools/power/turbostat: Relocate thermal probing code Introduce probe_thermal(), and move all thermal probing related code into it. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index ad9147757d5a..8dae576234a4 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4894,6 +4894,14 @@ void probe_rapl(void) rapl_probe_amd(); } +void probe_thermal(void) +{ + if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK)) + BIC_PRESENT(BIC_CORE_THROT_CNT); + else + BIC_NOT_PRESENT(BIC_CORE_THROT_CNT); +} + int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p) { unsigned long long msr; @@ -5598,14 +5606,11 @@ void process_cpuid() probe_rapl(); + probe_thermal(); + if (platform->has_nhm_msrs) BIC_PRESENT(BIC_SMI); - if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK)) - BIC_PRESENT(BIC_CORE_THROT_CNT); - else - BIC_NOT_PRESENT(BIC_CORE_THROT_CNT); - if (!quiet) decode_misc_feature_control(); -- cgit v1.2.3 From ce7a32c2a4cdba06ed5ead4ed8f980c893e20cd2 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 30 Aug 2023 16:36:06 +0800 Subject: tools/power/turbostat: Reorder some functions Reorder some functions to solve code depdency introduced by next patch. No functional change. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 214 +++++++++++++++++----------------- 1 file changed, 107 insertions(+), 107 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 8dae576234a4..eb333612bdec 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4878,92 +4878,6 @@ void rapl_probe_amd(void) fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); } -/* - * probe_rapl() - * - * sets rapl_power_units, rapl_energy_units, rapl_time_units - */ -void probe_rapl(void) -{ - if (!platform->rapl_msrs) - return; - - if (genuine_intel) - rapl_probe_intel(); - if (authentic_amd || hygon_genuine) - rapl_probe_amd(); -} - -void probe_thermal(void) -{ - if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK)) - BIC_PRESENT(BIC_CORE_THROT_CNT); - else - BIC_NOT_PRESENT(BIC_CORE_THROT_CNT); -} - -int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p) -{ - unsigned long long msr; - unsigned int dts, dts2; - int cpu; - - UNUSED(c); - UNUSED(p); - - if (!(do_dts || do_ptm)) - return 0; - - cpu = t->cpu_id; - - /* DTS is per-core, no need to print for each thread */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) - return 0; - - if (cpu_migrate(cpu)) { - fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu); - return -1; - } - - if (do_ptm && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) { - if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) - return 0; - - dts = (msr >> 16) & 0x7F; - fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", cpu, msr, tj_max - dts); - - if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr)) - return 0; - - dts = (msr >> 16) & 0x7F; - dts2 = (msr >> 8) & 0x7F; - fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", - cpu, msr, tj_max - dts, tj_max - dts2); - } - - if (do_dts && debug) { - unsigned int resolution; - - if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) - return 0; - - dts = (msr >> 16) & 0x7F; - resolution = (msr >> 27) & 0xF; - fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n", - cpu, msr, tj_max - dts, resolution); - - if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr)) - return 0; - - dts = (msr >> 16) & 0x7F; - dts2 = (msr >> 8) & 0x7F; - fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", - cpu, msr, tj_max - dts, tj_max - dts2); - } - - return 0; -} - void print_power_limit_msr(int cpu, unsigned long long msr, char *label) { fprintf(outf, "cpu%d: %s: %sabled (%0.3f Watts, %f sec, clamp %sabled)\n", @@ -5095,29 +5009,20 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) return 0; } -int get_cpu_type(struct thread_data *t, struct core_data *c, struct pkg_data *p) +/* + * probe_rapl() + * + * sets rapl_power_units, rapl_energy_units, rapl_time_units + */ +void probe_rapl(void) { - unsigned int eax, ebx, ecx, edx; - - UNUSED(c); - UNUSED(p); - - if (!genuine_intel) - return 0; - - if (cpu_migrate(t->cpu_id)) { - fprintf(outf, "Could not migrate to CPU %d\n", t->cpu_id); - return -1; - } - - if (max_level < 0x1a) - return 0; + if (!platform->rapl_msrs) + return; - __cpuid(0x1a, eax, ebx, ecx, edx); - eax = (eax >> 24) & 0xFF; - if (eax == 0x20) - t->is_atom = true; - return 0; + if (genuine_intel) + rapl_probe_intel(); + if (authentic_amd || hygon_genuine) + rapl_probe_amd(); } /* @@ -5200,6 +5105,101 @@ guess: return 0; } +int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p) +{ + unsigned long long msr; + unsigned int dts, dts2; + int cpu; + + UNUSED(c); + UNUSED(p); + + if (!(do_dts || do_ptm)) + return 0; + + cpu = t->cpu_id; + + /* DTS is per-core, no need to print for each thread */ + if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) + return 0; + + if (cpu_migrate(cpu)) { + fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu); + return -1; + } + + if (do_ptm && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) { + if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) + return 0; + + dts = (msr >> 16) & 0x7F; + fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", cpu, msr, tj_max - dts); + + if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr)) + return 0; + + dts = (msr >> 16) & 0x7F; + dts2 = (msr >> 8) & 0x7F; + fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", + cpu, msr, tj_max - dts, tj_max - dts2); + } + + if (do_dts && debug) { + unsigned int resolution; + + if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr)) + return 0; + + dts = (msr >> 16) & 0x7F; + resolution = (msr >> 27) & 0xF; + fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n", + cpu, msr, tj_max - dts, resolution); + + if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr)) + return 0; + + dts = (msr >> 16) & 0x7F; + dts2 = (msr >> 8) & 0x7F; + fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n", + cpu, msr, tj_max - dts, tj_max - dts2); + } + + return 0; +} + +void probe_thermal(void) +{ + if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK)) + BIC_PRESENT(BIC_CORE_THROT_CNT); + else + BIC_NOT_PRESENT(BIC_CORE_THROT_CNT); +} + +int get_cpu_type(struct thread_data *t, struct core_data *c, struct pkg_data *p) +{ + unsigned int eax, ebx, ecx, edx; + + UNUSED(c); + UNUSED(p); + + if (!genuine_intel) + return 0; + + if (cpu_migrate(t->cpu_id)) { + fprintf(outf, "Could not migrate to CPU %d\n", t->cpu_id); + return -1; + } + + if (max_level < 0x1a) + return 0; + + __cpuid(0x1a, eax, ebx, ecx, edx); + eax = (eax >> 24) & 0xFF; + if (eax == 0x20) + t->is_atom = true; + return 0; +} + void decode_feature_control_msr(void) { unsigned long long msr; -- cgit v1.2.3 From 5612b2c89bd0a3a2f7c9e8756e6ead971b03f8a3 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 30 Aug 2023 16:54:51 +0800 Subject: tools/power/turbostat: Relocate more probing related code Relocate more feature probing code outside of process_cpuids() into the corresponding probing functions. This improves the readability of code and the turbostat output. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 37 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index eb333612bdec..ffeee48e8d85 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5023,6 +5023,11 @@ void probe_rapl(void) rapl_probe_intel(); if (authentic_amd || hygon_genuine) rapl_probe_amd(); + + if (quiet) + return; + + for_all_cpus(print_rapl, ODD_COUNTERS); } /* @@ -5173,6 +5178,13 @@ void probe_thermal(void) BIC_PRESENT(BIC_CORE_THROT_CNT); else BIC_NOT_PRESENT(BIC_CORE_THROT_CNT); + + for_all_cpus(set_temperature_target, ODD_COUNTERS); + + if (quiet) + return; + + for_all_cpus(print_thermal, ODD_COUNTERS); } int get_cpu_type(struct thread_data *t, struct core_data *c, struct pkg_data *p) @@ -5380,6 +5392,7 @@ void probe_cstates(void) decode_c6_demotion_policy_msr(); print_dev_latency(); dump_sysfs_cstate_config(); + print_irtl(); } void probe_lpi(void) @@ -5413,6 +5426,10 @@ void probe_pstates(void) dump_turbo_ratio_info(); dump_sysfs_pstate_config(); decode_misc_pwr_mgmt_msr(); + + for_all_cpus(print_hwp, ODD_COUNTERS); + for_all_cpus(print_epb, ODD_COUNTERS); + for_all_cpus(print_perf_limit, ODD_COUNTERS); } void process_cpuid() @@ -5897,29 +5914,9 @@ void turbostat_init() process_cpuid(); linux_perf_init(); - if (!quiet) - for_all_cpus(print_hwp, ODD_COUNTERS); - - if (!quiet) - for_all_cpus(print_epb, ODD_COUNTERS); - - if (!quiet) - for_all_cpus(print_perf_limit, ODD_COUNTERS); - - if (!quiet) - for_all_cpus(print_rapl, ODD_COUNTERS); - - for_all_cpus(set_temperature_target, ODD_COUNTERS); - for_all_cpus(get_cpu_type, ODD_COUNTERS); for_all_cpus(get_cpu_type, EVEN_COUNTERS); - if (!quiet) - for_all_cpus(print_thermal, ODD_COUNTERS); - - if (!quiet) - print_irtl(); - if (DO_BIC(BIC_IPC)) (void)get_instr_count_fd(base_cpu); } -- cgit v1.2.3 From 7ee39d8d593e3d28eced0fa1a8c8c6bdcbd4156e Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 13 Sep 2023 23:32:39 +0800 Subject: tools/power/turbostat: Introduce probe_pm_features() Feature probe has nothing to do with CPUID, thus it should not be in process_cpuids(). Introduce probe_pm_features() and move all feature probing functions into it. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index ffeee48e8d85..607152b36c1a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5610,7 +5610,10 @@ void process_cpuid() BIC_PRESENT(BIC_IRQ); BIC_PRESENT(BIC_TSC_MHz); +} +void probe_pm_features(void) +{ probe_pstates(); probe_cstates(); @@ -5630,8 +5633,6 @@ void process_cpuid() if (!quiet) decode_misc_feature_control(); - - return; } /* @@ -5912,6 +5913,7 @@ void turbostat_init() check_dev_msr(); check_permissions(); process_cpuid(); + probe_pm_features(); linux_perf_init(); for_all_cpus(get_cpu_type, ODD_COUNTERS); -- cgit v1.2.3 From 05ad96ff0fb9d1b16abb5022b9c62636c6780fc2 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 27 Aug 2023 15:33:27 +0800 Subject: tools/power/turbostat: Enable MSR_CORE_C1_RES on recent Intel client platforms All recent Intel client platforms have MSR_CORE_C1_RES. Enable the support on these platforms, including CNL/ICL/LKF/RKL/TGL/ADL/RPL/MTL. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 607152b36c1a..9895f348b637 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -604,6 +604,7 @@ static const struct platform_features cnl_features = { .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC7 | PC8 | PC9 | PC10, .cst_limit = CST_LIMIT_HSW, .has_irtl_msrs = 1, + .has_msr_core_c1_res = 1, .has_ext_cst_msrs = 1, .trl_msrs = TRL_BASE, .tcc_offset_bits = 6, -- cgit v1.2.3 From 6b74a30b767e362eda7deeac52edcd546c5f6d8f Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 9 Sep 2023 13:26:51 +0800 Subject: tools/power/turbostat: Remove PC7/PC9 support on ADL/RPL Compared with other platforms that share cnl_features, ADL/RPL don't have PC7/PC9. Clone a new platform feature set from cnl_features for ADL/RPL, with PC7/PC9 removed. Signed-off-by: Zhang Rui Reviewed-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 9895f348b637..a769daa59b12 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -612,6 +612,23 @@ static const struct platform_features cnl_features = { .enable_tsc_tweak = 1, }; +static const struct platform_features adl_features = { + .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, + .has_config_tdp = 1, + .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10, + .cst_limit = CST_LIMIT_HSW, + .has_irtl_msrs = 1, + .has_msr_core_c1_res = 1, + .has_ext_cst_msrs = 1, + .trl_msrs = TRL_BASE, + .tcc_offset_bits = 6, + .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX, + .enable_tsc_tweak = 1, +}; + static const struct platform_features skx_features = { .has_msr_misc_feature_control = 1, .has_msr_misc_pwr_mgmt = 1, @@ -812,11 +829,11 @@ static const struct platform_data turbostat_pdata[] = { { INTEL_FAM6_SAPPHIRERAPIDS_X, &spr_features }, { INTEL_FAM6_EMERALDRAPIDS_X, &spr_features }, { INTEL_FAM6_LAKEFIELD, &cnl_features }, - { INTEL_FAM6_ALDERLAKE, &cnl_features }, - { INTEL_FAM6_ALDERLAKE_L, &cnl_features }, - { INTEL_FAM6_RAPTORLAKE, &cnl_features }, - { INTEL_FAM6_RAPTORLAKE_P, &cnl_features }, - { INTEL_FAM6_RAPTORLAKE_S, &cnl_features }, + { INTEL_FAM6_ALDERLAKE, &adl_features }, + { INTEL_FAM6_ALDERLAKE_L, &adl_features }, + { INTEL_FAM6_RAPTORLAKE, &adl_features }, + { INTEL_FAM6_RAPTORLAKE_P, &adl_features }, + { INTEL_FAM6_RAPTORLAKE_S, &adl_features }, { INTEL_FAM6_METEORLAKE, &cnl_features }, { INTEL_FAM6_METEORLAKE_L, &cnl_features }, { INTEL_FAM6_ATOM_SILVERMONT, &slv_features }, @@ -828,7 +845,7 @@ static const struct platform_data turbostat_pdata[] = { { INTEL_FAM6_ATOM_TREMONT_D, &tmtd_features }, { INTEL_FAM6_ATOM_TREMONT, &tmt_features }, { INTEL_FAM6_ATOM_TREMONT_L, &tmt_features }, - { INTEL_FAM6_ATOM_GRACEMONT, &cnl_features }, + { INTEL_FAM6_ATOM_GRACEMONT, &adl_features }, { INTEL_FAM6_XEON_PHI_KNL, &knl_features }, { INTEL_FAM6_XEON_PHI_KNM, &knl_features }, /* -- cgit v1.2.3 From 71cfd1da9f0635ccd7124ad8b67b9aed596be491 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 6 Oct 2023 11:01:17 +0800 Subject: tools/power/turbostat: Introduce cpu_allowed_set Turbostat supports "-c" parameter which limits output to system summary plus the specified cpu-set. But some code still uses cpu_present_set to read and dump the counters. Introduce cpu_allowed_set for code that should obey the specified cpu-set. No functional change. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a769daa59b12..d8f44ea5b4bf 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -904,8 +904,8 @@ int backwards_count; char *progname; #define CPU_SUBSET_MAXCPUS 1024 /* need to use before probe... */ -cpu_set_t *cpu_present_set, *cpu_affinity_set, *cpu_subset; -size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size; +cpu_set_t *cpu_present_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset; +size_t cpu_present_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size; #define MAX_ADDED_COUNTERS 8 #define MAX_ADDED_THREAD_COUNTERS 24 #define BITMASK_SIZE 32 @@ -1157,6 +1157,11 @@ int cpu_is_not_present(int cpu) return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set); } +int cpu_is_not_allowed(int cpu) +{ + return !CPU_ISSET_S(cpu, cpu_allowed_setsize, cpu_allowed_set); +} + /* * run func(thread, core, package) in topology order * skip non-present cpus @@ -3396,6 +3401,10 @@ void free_all_buffers(void) cpu_present_set = NULL; cpu_present_setsize = 0; + CPU_FREE(cpu_allowed_set); + cpu_allowed_set = NULL; + cpu_allowed_setsize = 0; + CPU_FREE(cpu_affinity_set); cpu_affinity_set = NULL; cpu_affinity_setsize = 0; @@ -5697,13 +5706,29 @@ void topology_probe() CPU_ZERO_S(cpu_present_setsize, cpu_present_set); for_all_proc_cpus(mark_cpu_present); + /* + * Allocate and initialize cpu_allowed_set + */ + cpu_allowed_set = CPU_ALLOC((topo.max_cpu_num + 1)); + if (cpu_allowed_set == NULL) + err(3, "CPU_ALLOC"); + cpu_allowed_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); + CPU_ZERO_S(cpu_allowed_setsize, cpu_allowed_set); + /* * Validate that all cpus in cpu_subset are also in cpu_present_set */ for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) { - if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset)) + if (!cpu_subset) { + if (CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) + CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); + continue; + } + if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset)) { if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) err(1, "cpu%d not present", i); + CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); + } } /* -- cgit v1.2.3 From 4ede6d1ce7acba9cafe7df4e935b174623cd2181 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 4 Oct 2023 13:52:02 +0800 Subject: tools/power/turbostat: Obey allowed CPUs when accessing CPU counters for_all_cpus/for_all_cpus_2 are used for accessing the per CPU counters, and they should follow the cpu_allowed_set instead of cpu_present_set. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index d8f44ea5b4bf..202cf5231d7a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1182,7 +1182,7 @@ int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pk t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no); - if (cpu_is_not_present(t->cpu_id)) + if (cpu_is_not_allowed(t->cpu_id)) continue; c = GET_CORE(core_base, core_no, node_no, pkg_no); @@ -3618,7 +3618,7 @@ int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *, t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no); - if (cpu_is_not_present(t->cpu_id)) + if (cpu_is_not_allowed(t->cpu_id)) continue; t2 = GET_THREAD(thread_base2, thread_no, core_no, node_no, pkg_no); -- cgit v1.2.3 From 7bb3fe27ad4f62039b2ac80a2147452a608b474f Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 4 Oct 2023 14:25:25 +0800 Subject: tools/power/turbostat: Obey allowed CPUs during startup Set turbostat CPU affinity to make sure turbostat is running on one of the allowed CPUs. Set base_cpu to the first allowed CPU so that some platform information is dumped using one of the allowed CPUs. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 202cf5231d7a..f81ce832d17a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5731,6 +5731,10 @@ void topology_probe() } } + if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set)) + err(-ENODEV, "No valid cpus found"); + sched_setaffinity(0, cpu_allowed_setsize, cpu_allowed_set); + /* * Allocate and initialize cpu_affinity_set */ @@ -5941,12 +5945,17 @@ void setup_all_buffers(void) void set_base_cpu(void) { - base_cpu = sched_getcpu(); - if (base_cpu < 0) - err(-ENODEV, "No valid cpus found"); + int i; - if (debug > 1) - fprintf(outf, "base_cpu = %d\n", base_cpu); + for (i = 0; i < topo.max_cpu_num + 1; ++i) { + if (cpu_is_not_allowed(i)) + continue; + base_cpu = i; + if (debug > 1) + fprintf(outf, "base_cpu = %d\n", base_cpu); + return; + } + err(-ENODEV, "No valid cpus found"); } void turbostat_init() @@ -5976,8 +5985,6 @@ int fork_it(char **argv) first_counter_read = 0; if (status) exit(status); - /* clear affinity side-effect of get_counters() */ - sched_setaffinity(0, cpu_present_setsize, cpu_present_set); gettimeofday(&tv_even, (struct timezone *)NULL); child_pid = fork(); -- cgit v1.2.3 From 74318add132365db3026e281ac06836a26cda857 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 4 Oct 2023 15:13:23 +0800 Subject: tools/power/turbostat: Abstract several functions When detecting the primary thread/core in a core/package, current code doesn't handle the allowed CPUs. Abstract several functions for further fix of this issue. No functional change. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 58 +++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index f81ce832d17a..5f6bc076e1dd 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1198,6 +1198,30 @@ int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pk return 0; } +int is_cpu_first_thread_in_core(struct thread_data *t, struct core_data *c, struct pkg_data *p) +{ + UNUSED(c); + UNUSED(p); + + return (t->flags & CPU_IS_FIRST_THREAD_IN_CORE); +} + +int is_cpu_first_core_in_package(struct thread_data *t, struct core_data *c, struct pkg_data *p) +{ + UNUSED(c); + UNUSED(p); + + return (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE); +} + +int is_cpu_first_thread_in_package(struct thread_data *t, struct core_data *c, struct pkg_data *p) +{ + UNUSED(c); + UNUSED(p); + + return (t->flags & CPU_IS_FIRST_THREAD_IN_CORE) && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE); +} + int cpu_migrate(int cpu) { CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set); @@ -1682,11 +1706,11 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data int printed = 0; /* if showing only 1st thread in core and this isn't one, bail out */ - if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) + if (show_core_only && !is_cpu_first_thread_in_core(t, c, p)) return 0; /* if showing only 1st thread in pkg and this isn't one, bail out */ - if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (show_pkg_only && !is_cpu_first_core_in_package(t, c, p)) return 0; /*if not summary line and --cpu is used */ @@ -1820,7 +1844,7 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1 / tsc); /* print per-core data only for 1st thread in core */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) + if (!is_cpu_first_thread_in_core(t, c, p)) goto done; if (DO_BIC(BIC_CPU_c3)) @@ -1867,7 +1891,7 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units); /* print per-package data only for 1st core in package */ - if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (!is_cpu_first_core_in_package(t, c, p)) goto done; /* PkgTmp */ @@ -2202,7 +2226,7 @@ int delta_cpu(struct thread_data *t, struct core_data *c, int retval = 0; /* calculate core delta only for 1st thread in core */ - if (t->flags & CPU_IS_FIRST_THREAD_IN_CORE) + if (is_cpu_first_thread_in_core(t, c, p)) delta_core(c, c2); /* always calculate thread delta */ @@ -2211,7 +2235,7 @@ int delta_cpu(struct thread_data *t, struct core_data *c, return retval; /* calculate package delta only for 1st core in package */ - if (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE) + if (is_cpu_first_core_in_package(t, c, p)) retval = delta_package(p, p2); return retval; @@ -2325,7 +2349,7 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) } /* sum per-core values only for 1st thread in core */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) + if (!is_cpu_first_thread_in_core(t, c, p)) return 0; average.cores.c3 += c->c3; @@ -2345,7 +2369,7 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) } /* sum per-pkg values only for 1st core in pkg */ - if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (!is_cpu_first_core_in_package(t, c, p)) return 0; if (DO_BIC(BIC_Totl_c0)) @@ -2745,7 +2769,7 @@ retry: } /* collect core counters only for 1st thread in core */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) + if (!is_cpu_first_thread_in_core(t, c, p)) goto done; if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) { @@ -2800,7 +2824,7 @@ retry: } /* collect package counters only for 1st core in package */ - if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (!is_cpu_first_core_in_package(t, c, p)) goto done; if (DO_BIC(BIC_Totl_c0)) { @@ -4581,7 +4605,7 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p) cpu = t->cpu_id; /* EPB is per-package */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (!is_cpu_first_thread_in_package(t, c, p)) return 0; if (cpu_migrate(cpu)) { @@ -4630,7 +4654,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) cpu = t->cpu_id; /* MSR_HWP_CAPABILITIES is per-package */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (!is_cpu_first_thread_in_package(t, c, p)) return 0; if (cpu_migrate(cpu)) { @@ -4713,7 +4737,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data cpu = t->cpu_id; /* per-package */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (!is_cpu_first_thread_in_package(t, c, p)) return 0; if (cpu_migrate(cpu)) { @@ -4930,7 +4954,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) return 0; /* RAPL counters are per package, so print only for 1st thread/package */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (!is_cpu_first_thread_in_package(t, c, p)) return 0; cpu = t->cpu_id; @@ -5083,7 +5107,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk return 0; /* this is a per-package concept */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) + if (!is_cpu_first_thread_in_package(t, c, p)) return 0; cpu = t->cpu_id; @@ -5152,7 +5176,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p cpu = t->cpu_id; /* DTS is per-core, no need to print for each thread */ - if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) + if (!is_cpu_first_thread_in_core(t, c, p)) return 0; if (cpu_migrate(cpu)) { @@ -5160,7 +5184,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p return -1; } - if (do_ptm && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) { + if (do_ptm && is_cpu_first_core_in_package(t, c, p)) { if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) return 0; -- cgit v1.2.3 From ccf8a0528061b4ca5f5c0e73c8d888e7e6d8b054 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 6 Oct 2023 09:59:14 +0800 Subject: tools/power/turbostat: Obey allowed CPUs for primary thread/core detection Thread_id doesn't tell if a CPU is allowed or not. Detect allowed CPUs only and use the first detected thread/core as the primary thread/core of a core/package. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 5f6bc076e1dd..e586164906fa 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -926,12 +926,11 @@ struct thread_data { unsigned int x2apic_id; unsigned int flags; bool is_atom; -#define CPU_IS_FIRST_THREAD_IN_CORE 0x2 -#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4 unsigned long long counter[MAX_ADDED_THREAD_COUNTERS]; } *thread_even, *thread_odd; struct core_data { + int base_cpu; unsigned long long c3; unsigned long long c6; unsigned long long c7; @@ -944,6 +943,7 @@ struct core_data { } *core_even, *core_odd; struct pkg_data { + int base_cpu; unsigned long long pc2; unsigned long long pc3; unsigned long long pc6; @@ -1200,26 +1200,21 @@ int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pk int is_cpu_first_thread_in_core(struct thread_data *t, struct core_data *c, struct pkg_data *p) { - UNUSED(c); UNUSED(p); - return (t->flags & CPU_IS_FIRST_THREAD_IN_CORE); + return ((int)t->cpu_id == c->base_cpu || c->base_cpu < 0); } int is_cpu_first_core_in_package(struct thread_data *t, struct core_data *c, struct pkg_data *p) { UNUSED(c); - UNUSED(p); - return (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE); + return ((int)t->cpu_id == p->base_cpu || p->base_cpu < 0); } int is_cpu_first_thread_in_package(struct thread_data *t, struct core_data *c, struct pkg_data *p) { - UNUSED(c); - UNUSED(p); - - return (t->flags & CPU_IS_FIRST_THREAD_IN_CORE) && (t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE); + return is_cpu_first_thread_in_core(t, c, p) && is_cpu_first_core_in_package(t, c, p); } int cpu_migrate(int cpu) @@ -2263,9 +2258,6 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data t->irq_count = 0; t->smi_count = 0; - /* tells format_counters to dump all fields from this set */ - t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; - c->c3 = 0; c->c6 = 0; c->c7 = 0; @@ -5872,15 +5864,19 @@ void allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_ if (*c == NULL) goto error; - for (i = 0; i < num_cores; i++) + for (i = 0; i < num_cores; i++) { (*c)[i].core_id = -1; + (*c)[i].base_cpu = -1; + } *p = calloc(topo.num_packages, sizeof(struct pkg_data)); if (*p == NULL) goto error; - for (i = 0; i < topo.num_packages; i++) + for (i = 0; i < topo.num_packages; i++) { (*p)[i].package_id = i; + (*p)[i].base_cpu = -1; + } return; error: @@ -5913,10 +5909,11 @@ void init_counter(struct thread_data *thread_base, struct core_data *core_base, p = GET_PKG(pkg_base, pkg_id); t->cpu_id = cpu_id; - if (thread_id == 0) { - t->flags |= CPU_IS_FIRST_THREAD_IN_CORE; - if (cpu_is_first_core_in_package(cpu_id)) - t->flags |= CPU_IS_FIRST_CORE_IN_PACKAGE; + if (!cpu_is_not_allowed(cpu_id)) { + if (c->base_cpu < 0) + c->base_cpu = t->cpu_id; + if (p->base_cpu < 0) + p->base_cpu = t->cpu_id; } c->core_id = core_id; -- cgit v1.2.3 From 0fe3752901370b83b63d4ddbce708b23c8e41ea9 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 6 Oct 2023 18:35:26 +0800 Subject: tools/power/turbostat: Obey allowed CPUs for system summary System summary should summarize the information for allowed CPUs instead of all the present CPUs. Introduce topology information for allowed CPUs, and use them to get system summary. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 71 +++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 25 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index e586164906fa..91aa03989317 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1134,6 +1134,9 @@ struct topo_params { int num_die; int num_cpus; int num_cores; + int allowed_packages; + int allowed_cpus; + int allowed_cores; int max_cpu_num; int max_node_num; int nodes_per_pkg; @@ -1179,7 +1182,6 @@ int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pk struct thread_data *t; struct core_data *c; struct pkg_data *p; - t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no); if (cpu_is_not_allowed(t->cpu_id)) @@ -2426,40 +2428,40 @@ void compute_average(struct thread_data *t, struct core_data *c, struct pkg_data /* Use the global time delta for the average. */ average.threads.tv_delta = tv_delta; - average.threads.tsc /= topo.num_cpus; - average.threads.aperf /= topo.num_cpus; - average.threads.mperf /= topo.num_cpus; - average.threads.instr_count /= topo.num_cpus; - average.threads.c1 /= topo.num_cpus; + average.threads.tsc /= topo.allowed_cpus; + average.threads.aperf /= topo.allowed_cpus; + average.threads.mperf /= topo.allowed_cpus; + average.threads.instr_count /= topo.allowed_cpus; + average.threads.c1 /= topo.allowed_cpus; if (average.threads.irq_count > 9999999) sums_need_wide_columns = 1; - average.cores.c3 /= topo.num_cores; - average.cores.c6 /= topo.num_cores; - average.cores.c7 /= topo.num_cores; - average.cores.mc6_us /= topo.num_cores; + average.cores.c3 /= topo.allowed_cores; + average.cores.c6 /= topo.allowed_cores; + average.cores.c7 /= topo.allowed_cores; + average.cores.mc6_us /= topo.allowed_cores; if (DO_BIC(BIC_Totl_c0)) - average.packages.pkg_wtd_core_c0 /= topo.num_packages; + average.packages.pkg_wtd_core_c0 /= topo.allowed_packages; if (DO_BIC(BIC_Any_c0)) - average.packages.pkg_any_core_c0 /= topo.num_packages; + average.packages.pkg_any_core_c0 /= topo.allowed_packages; if (DO_BIC(BIC_GFX_c0)) - average.packages.pkg_any_gfxe_c0 /= topo.num_packages; + average.packages.pkg_any_gfxe_c0 /= topo.allowed_packages; if (DO_BIC(BIC_CPUGFX)) - average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages; + average.packages.pkg_both_core_gfxe_c0 /= topo.allowed_packages; - average.packages.pc2 /= topo.num_packages; + average.packages.pc2 /= topo.allowed_packages; if (DO_BIC(BIC_Pkgpc3)) - average.packages.pc3 /= topo.num_packages; + average.packages.pc3 /= topo.allowed_packages; if (DO_BIC(BIC_Pkgpc6)) - average.packages.pc6 /= topo.num_packages; + average.packages.pc6 /= topo.allowed_packages; if (DO_BIC(BIC_Pkgpc7)) - average.packages.pc7 /= topo.num_packages; + average.packages.pc7 /= topo.allowed_packages; - average.packages.pc8 /= topo.num_packages; - average.packages.pc9 /= topo.num_packages; - average.packages.pc10 /= topo.num_packages; + average.packages.pc8 /= topo.allowed_packages; + average.packages.pc9 /= topo.allowed_packages; + average.packages.pc10 /= topo.allowed_packages; for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { if (mp->format == FORMAT_RAW) @@ -2469,7 +2471,7 @@ void compute_average(struct thread_data *t, struct core_data *c, struct pkg_data sums_need_wide_columns = 1; continue; } - average.threads.counter[i] /= topo.num_cpus; + average.threads.counter[i] /= topo.allowed_cpus; } for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { if (mp->format == FORMAT_RAW) @@ -2478,7 +2480,7 @@ void compute_average(struct thread_data *t, struct core_data *c, struct pkg_data if (average.cores.counter[i] > 9999999) sums_need_wide_columns = 1; } - average.cores.counter[i] /= topo.num_cores; + average.cores.counter[i] /= topo.allowed_cores; } for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { if (mp->format == FORMAT_RAW) @@ -2487,7 +2489,7 @@ void compute_average(struct thread_data *t, struct core_data *c, struct pkg_data if (average.packages.counter[i] > 9999999) sums_need_wide_columns = 1; } - average.packages.counter[i] /= topo.num_packages; + average.packages.counter[i] /= topo.allowed_packages; } } @@ -3690,7 +3692,7 @@ void re_initialize(void) { free_all_buffers(); setup_all_buffers(); - fprintf(outf, "turbostat: re-initialized with num_cpus %d\n", topo.num_cpus); + fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus); } void set_max_cpu_num(void) @@ -5953,6 +5955,24 @@ void allocate_irq_buffers(void) err(-1, "calloc %d", topo.max_cpu_num + 1); } +int update_topo(struct thread_data *t, struct core_data *c, struct pkg_data *p) +{ + topo.allowed_cpus++; + if ((int)t->cpu_id == c->base_cpu) + topo.allowed_cores++; + if ((int)t->cpu_id == p->base_cpu) + topo.allowed_packages++; + + return 0; +} + +void topology_update(void) +{ + topo.allowed_cpus = 0; + topo.allowed_cores = 0; + topo.allowed_packages = 0; + for_all_cpus(update_topo, ODD_COUNTERS); +} void setup_all_buffers(void) { topology_probe(); @@ -5962,6 +5982,7 @@ void setup_all_buffers(void) allocate_counters(&thread_odd, &core_odd, &package_odd); allocate_output_buffer(); for_all_proc_cpus(initialize_counters); + topology_update(); } void set_base_cpu(void) -- cgit v1.2.3 From c25ef0e5d9d7d5fb9e1679286fc7a11e70f16c70 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 20 Oct 2023 14:20:47 +0800 Subject: tools/power/turbostat: Handle offlined CPUs in cpu_subset It is possible that the cpu_subset contains offlined CPUs. If this happens during start, exit immediately because this is likely an operator error that is best fixed by re-invoking. If this happens at runtime, give a warning only because turbostat should do its best effort to continue running. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 91aa03989317..f9ea07961a22 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1149,7 +1149,7 @@ struct timeval tv_even, tv_odd, tv_delta; int *irq_column_2_cpu; /* /proc/interrupts column numbers */ int *irqs_per_cpu; /* indexed by cpu_num */ -void setup_all_buffers(void); +void setup_all_buffers(bool startup); char *sys_lpi_file; char *sys_lpi_file_sysfs = "/sys/devices/system/cpu/cpuidle/low_power_idle_system_residency_us"; @@ -3691,7 +3691,7 @@ int for_all_proc_cpus(int (func) (int)) void re_initialize(void) { free_all_buffers(); - setup_all_buffers(); + setup_all_buffers(false); fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus); } @@ -5692,7 +5692,7 @@ int dir_filter(const struct dirent *dirp) return 0; } -void topology_probe() +void topology_probe(bool startup) { int i; int max_core_id = 0; @@ -5734,7 +5734,12 @@ void topology_probe() CPU_ZERO_S(cpu_allowed_setsize, cpu_allowed_set); /* - * Validate that all cpus in cpu_subset are also in cpu_present_set + * Validate cpu_subset and update cpu_allowed_set. + * + * Make sure all cpus in cpu_subset are also in cpu_present_set during startup, + * and give a warning when cpus in cpu_subset become unavailable at runtime. + * + * cpu_allowed_set is the intersection of cpu_present_set and cpu_subset. */ for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) { if (!cpu_subset) { @@ -5743,9 +5748,15 @@ void topology_probe() continue; } if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset)) { - if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) - err(1, "cpu%d not present", i); - CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); + if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) { + /* all cpus in cpu_subset must be in cpu_present_set during startup */ + if (startup) + err(1, "cpu%d not present", i); + else + fprintf(stderr, "cpu%d not present\n", i); + } else { + CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); + } } } @@ -5973,9 +5984,9 @@ void topology_update(void) topo.allowed_packages = 0; for_all_cpus(update_topo, ODD_COUNTERS); } -void setup_all_buffers(void) +void setup_all_buffers(bool startup) { - topology_probe(); + topology_probe(startup); allocate_irq_buffers(); allocate_fd_percpu(); allocate_counters(&thread_even, &core_even, &package_even); @@ -6002,7 +6013,7 @@ void set_base_cpu(void) void turbostat_init() { - setup_all_buffers(); + setup_all_buffers(true); set_base_cpu(); check_dev_msr(); check_permissions(); -- cgit v1.2.3 From 8c3dd2c9e54273922ea71b2a4c0e77fc624c396b Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 20 Oct 2023 09:45:21 +0800 Subject: tools/power/turbostat: Abstrct function for parsing cpu string Abstract parse_cpu_str() which can update any specified cpu_set by a given cpu string. This can be used to handle further CPU limitations from other sources like cgroup. The cpu string parsing code is also enhanced to handle the strings that have an extra '\n' before string terminator. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 104 ++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 49 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index f9ea07961a22..3a759b49f25e 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -3565,6 +3565,59 @@ int get_physical_node_id(struct cpu_topology *thiscpu) return -1; } +static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size) +{ + unsigned int start, end; + char *next = cpu_str; + + while (next && *next) { + + if (*next == '-') /* no negative cpu numbers */ + return 1; + + start = strtoul(next, &next, 10); + + if (start >= CPU_SUBSET_MAXCPUS) + return 1; + CPU_SET_S(start, cpu_set_size, cpu_set); + + if (*next == '\0' || *next == '\n') + break; + + if (*next == ',') { + next += 1; + continue; + } + + if (*next == '-') { + next += 1; /* start range */ + } else if (*next == '.') { + next += 1; + if (*next == '.') + next += 1; /* start range */ + else + return 1; + } + + end = strtoul(next, &next, 10); + if (end <= start) + return 1; + + while (++start <= end) { + if (start >= CPU_SUBSET_MAXCPUS) + return 1; + CPU_SET_S(start, cpu_set_size, cpu_set); + } + + if (*next == ',') + next += 1; + else if (*next != '\0' && *next != '\n') + return 1; + } + + return 0; +} + int get_thread_siblings(struct cpu_topology *thiscpu) { char path[80], character; @@ -6384,9 +6437,6 @@ void probe_sysfs(void) */ void parse_cpu_command(char *optarg) { - unsigned int start, end; - char *next; - if (!strcmp(optarg, "core")) { if (cpu_subset) goto error; @@ -6409,52 +6459,8 @@ void parse_cpu_command(char *optarg) CPU_ZERO_S(cpu_subset_size, cpu_subset); - next = optarg; - - while (next && *next) { - - if (*next == '-') /* no negative cpu numbers */ - goto error; - - start = strtoul(next, &next, 10); - - if (start >= CPU_SUBSET_MAXCPUS) - goto error; - CPU_SET_S(start, cpu_subset_size, cpu_subset); - - if (*next == '\0') - break; - - if (*next == ',') { - next += 1; - continue; - } - - if (*next == '-') { - next += 1; /* start range */ - } else if (*next == '.') { - next += 1; - if (*next == '.') - next += 1; /* start range */ - else - goto error; - } - - end = strtoul(next, &next, 10); - if (end <= start) - goto error; - - while (++start <= end) { - if (start >= CPU_SUBSET_MAXCPUS) - goto error; - CPU_SET_S(start, cpu_subset_size, cpu_subset); - } - - if (*next == ',') - next += 1; - else if (*next != '\0') - goto error; - } + if (parse_cpu_str(optarg, cpu_subset, cpu_subset_size)) + goto error; return; -- cgit v1.2.3 From f638858da0925b29122f05135663013dc240eaf9 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 20 Oct 2023 09:39:22 +0800 Subject: tools/power/turbostat: Handle cgroup v2 cpu limitation CPUs can be isolated via cgroup settings and turbostat should avoid migrating to these CPUs, just like it does for the '-c' cpus. Introduce cpu_effective_set to save the cgroup cpu limitation info from /sys/fs/cgroup/cpuset.cpus.effective. And use cpu_allowed_set as the intersection of cpu_present_set, cpu_effective_set and cpu_subset. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 95 +++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 3a759b49f25e..0ef6fba118b1 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -904,8 +904,8 @@ int backwards_count; char *progname; #define CPU_SUBSET_MAXCPUS 1024 /* need to use before probe... */ -cpu_set_t *cpu_present_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset; -size_t cpu_present_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size; +cpu_set_t *cpu_present_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset; +size_t cpu_present_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size; #define MAX_ADDED_COUNTERS 8 #define MAX_ADDED_THREAD_COUNTERS 24 #define BITMASK_SIZE 32 @@ -3419,6 +3419,10 @@ void free_all_buffers(void) cpu_present_set = NULL; cpu_present_setsize = 0; + CPU_FREE(cpu_effective_set); + cpu_effective_set = NULL; + cpu_effective_setsize = 0; + CPU_FREE(cpu_allowed_set); cpu_allowed_set = NULL; cpu_allowed_setsize = 0; @@ -3741,6 +3745,46 @@ int for_all_proc_cpus(int (func) (int)) return 0; } +#define PATH_EFFECTIVE_CPUS "/sys/fs/cgroup/cpuset.cpus.effective" + +static char cpu_effective_str[1024]; + +static int update_effective_str(bool startup) +{ + FILE *fp; + char *pos; + char buf[1024]; + int ret; + + if (cpu_effective_str[0] == '\0' && !startup) + return 0; + + fp = fopen(PATH_EFFECTIVE_CPUS, "r"); + if (!fp) + return 0; + + pos = fgets(buf, 1024, fp); + if (!pos) + err(1, "%s: file read failed\n", PATH_EFFECTIVE_CPUS); + + fclose(fp); + + ret = strncmp(cpu_effective_str, buf, 1024); + if (!ret) + return 0; + + strncpy(cpu_effective_str, buf, 1024); + return 1; +} + +static void update_effective_set(bool startup) +{ + update_effective_str(startup); + + if (parse_cpu_str(cpu_effective_str, cpu_effective_set, cpu_effective_setsize)) + err(1, "%s: cpu str malformat %s\n", PATH_EFFECTIVE_CPUS, cpu_effective_str); +} + void re_initialize(void) { free_all_buffers(); @@ -4257,6 +4301,10 @@ restart: re_initialize(); goto restart; } + if (update_effective_str(false)) { + re_initialize(); + goto restart; + } do_sleep(); if (snapshot_proc_sysfs_files()) goto restart; @@ -5777,6 +5825,16 @@ void topology_probe(bool startup) CPU_ZERO_S(cpu_present_setsize, cpu_present_set); for_all_proc_cpus(mark_cpu_present); + /* + * Allocate and initialize cpu_effective_set + */ + cpu_effective_set = CPU_ALLOC((topo.max_cpu_num + 1)); + if (cpu_effective_set == NULL) + err(3, "CPU_ALLOC"); + cpu_effective_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); + CPU_ZERO_S(cpu_effective_setsize, cpu_effective_set); + update_effective_set(startup); + /* * Allocate and initialize cpu_allowed_set */ @@ -5787,30 +5845,37 @@ void topology_probe(bool startup) CPU_ZERO_S(cpu_allowed_setsize, cpu_allowed_set); /* - * Validate cpu_subset and update cpu_allowed_set. + * Validate and update cpu_allowed_set. * - * Make sure all cpus in cpu_subset are also in cpu_present_set during startup, - * and give a warning when cpus in cpu_subset become unavailable at runtime. + * Make sure all cpus in cpu_subset are also in cpu_present_set during startup. + * Give a warning when cpus in cpu_subset become unavailable at runtime. + * Give a warning when cpus are not effective because of cgroup setting. * - * cpu_allowed_set is the intersection of cpu_present_set and cpu_subset. + * cpu_allowed_set is the intersection of cpu_present_set/cpu_effective_set/cpu_subset. */ for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) { - if (!cpu_subset) { - if (CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) - CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); + if (cpu_subset && !CPU_ISSET_S(i, cpu_subset_size, cpu_subset)) continue; - } - if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset)) { - if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) { - /* all cpus in cpu_subset must be in cpu_present_set during startup */ + + if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) { + if (cpu_subset) { + /* cpus in cpu_subset must be in cpu_present_set during startup */ if (startup) err(1, "cpu%d not present", i); else fprintf(stderr, "cpu%d not present\n", i); - } else { - CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); } + continue; } + + if (CPU_COUNT_S(cpu_effective_setsize, cpu_effective_set)) { + if (!CPU_ISSET_S(i, cpu_effective_setsize, cpu_effective_set)) { + fprintf(stderr, "cpu%d not effective\n", i); + continue; + } + } + + CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set); } if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set)) -- cgit v1.2.3 From 37f68a2940558b4f6f8e51b7b1d00f084b4bdde2 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 24 Jan 2023 10:39:53 -0800 Subject: tools/power/turbostat: Move process to root cgroup When available CPUs are reduced via cgroup cpuset controller, turbostat will exit with errors (For example): get_counters: Could not migrate to CPU 0 turbostat: re-initialized with num_cpus 20 get_counters: Could not migrate to CPU 0 turbostat: re-initialized with num_cpus 20 Move the turbostat to root cgroup, which has every CPU. Writing the value 0 to a cgroup.procs file causes the writing process to be moved to the corresponding cgroup. Signed-off-by: Srinivas Pandruvada Tested-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 0ef6fba118b1..fea63d9d8e02 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -6666,6 +6666,19 @@ void cmdline(int argc, char **argv) int main(int argc, char **argv) { + int fd, ret; + + fd = open("/sys/fs/cgroup/cgroup.procs", O_WRONLY); + if (fd < 0) + goto skip_cgroup_setting; + + ret = write(fd, "0\n", 2); + if (ret == -1) + perror("Can't update cgroup\n"); + + close(fd); + +skip_cgroup_setting: outf = stderr; cmdline(argc, argv); -- cgit v1.2.3 From 0e3f10e6aa97b0134b526ec9cdc3ccdac2239b43 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 19 Oct 2023 11:04:33 +0800 Subject: tools/power/turbostat: Add MSR_CORE_C1_RES support for spr_features Add MSR_CORE_C1_RES support for spr_features because both Sapphirerapids and Emeraldrapids support this MSR. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index fea63d9d8e02..bbeeec02bf5b 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -667,6 +667,7 @@ static const struct platform_features spr_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_SKX, + .has_msr_core_c1_res = 1, .has_irtl_msrs = 1, .has_cst_prewake_bit = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, -- cgit v1.2.3 From 5feab4a6b8a730438a0fe8758dfa0700f951edde Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sat, 9 Sep 2023 13:28:07 +0800 Subject: tools/power/turbostat: Add initial support for GraniteRapids Add initial support for GraniteRapids. It shares the same features with SapphireRapids. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index bbeeec02bf5b..981d39454b49 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -829,6 +829,7 @@ static const struct platform_data turbostat_pdata[] = { { INTEL_FAM6_TIGERLAKE, &cnl_features }, { INTEL_FAM6_SAPPHIRERAPIDS_X, &spr_features }, { INTEL_FAM6_EMERALDRAPIDS_X, &spr_features }, + { INTEL_FAM6_GRANITERAPIDS_X, &spr_features }, { INTEL_FAM6_LAKEFIELD, &cnl_features }, { INTEL_FAM6_ALDERLAKE, &adl_features }, { INTEL_FAM6_ALDERLAKE_L, &adl_features }, -- cgit v1.2.3 From d33605f367414c7e0009978d1fbe9af01a36e221 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 28 Sep 2023 13:09:02 +0800 Subject: tools/power/turbostat: Add initial support for SierraForest Add initial support for SierraForest. It shares the same features with SapphireRapids, except that it has MSR_MODULE_C6_RES_MS support. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 981d39454b49..a50b6d071f6a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -674,6 +674,22 @@ static const struct platform_features spr_features = { .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; +static const struct platform_features srf_features = { + .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, + .has_config_tdp = 1, + .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC6 | PC2 | PC6, + .cst_limit = CST_LIMIT_SKX, + .has_msr_core_c1_res = 1, + .has_msr_module_c6_res_ms = 1, + .has_irtl_msrs = 1, + .has_cst_prewake_bit = 1, + .trl_msrs = TRL_BASE | TRL_CORECOUNT, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, +}; + static const struct platform_features slv_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, @@ -848,6 +864,7 @@ static const struct platform_data turbostat_pdata[] = { { INTEL_FAM6_ATOM_TREMONT, &tmt_features }, { INTEL_FAM6_ATOM_TREMONT_L, &tmt_features }, { INTEL_FAM6_ATOM_GRACEMONT, &adl_features }, + { INTEL_FAM6_ATOM_CRESTMONT_X, &srf_features }, { INTEL_FAM6_XEON_PHI_KNL, &knl_features }, { INTEL_FAM6_XEON_PHI_KNM, &knl_features }, /* -- cgit v1.2.3 From 5a6efcb9102af4210d5a59182dbfbc594ae50fd4 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 19 Oct 2023 11:00:07 +0800 Subject: tools/power/turbostat: Add initial support for GrandRidge Add initial support for GrandRidge. It shares the same features as SierraForest, except that it does not support PC2/PC6. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a50b6d071f6a..3407f08593f8 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -690,6 +690,22 @@ static const struct platform_features srf_features = { .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, }; +static const struct platform_features grr_features = { + .has_msr_misc_feature_control = 1, + .has_msr_misc_pwr_mgmt = 1, + .has_nhm_msrs = 1, + .has_config_tdp = 1, + .bclk_freq = BCLK_100MHZ, + .supported_cstates = CC1 | CC6, + .cst_limit = CST_LIMIT_SKX, + .has_msr_core_c1_res = 1, + .has_msr_module_c6_res_ms = 1, + .has_irtl_msrs = 1, + .has_cst_prewake_bit = 1, + .trl_msrs = TRL_BASE | TRL_CORECOUNT, + .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL, +}; + static const struct platform_features slv_features = { .has_nhm_msrs = 1, .bclk_freq = BCLK_SLV, @@ -865,6 +881,7 @@ static const struct platform_data turbostat_pdata[] = { { INTEL_FAM6_ATOM_TREMONT_L, &tmt_features }, { INTEL_FAM6_ATOM_GRACEMONT, &adl_features }, { INTEL_FAM6_ATOM_CRESTMONT_X, &srf_features }, + { INTEL_FAM6_ATOM_CRESTMONT, &grr_features }, { INTEL_FAM6_XEON_PHI_KNL, &knl_features }, { INTEL_FAM6_XEON_PHI_KNM, &knl_features }, /* -- cgit v1.2.3 From 7b57e7b683e3872b02117f46bd7dc7ad765888a8 Mon Sep 17 00:00:00 2001 From: Sumeet Pawnikar Date: Tue, 23 May 2023 17:46:45 +0530 Subject: tools/power/turbostat: Add initial support for ArrowLake Add initial support for ArrowLake platform. It shares the same features with CannonLake. Signed-off-by: Sumeet Pawnikar --- tools/power/x86/turbostat/turbostat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 3407f08593f8..6c52cceae1d7 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -870,6 +870,7 @@ static const struct platform_data turbostat_pdata[] = { { INTEL_FAM6_RAPTORLAKE_S, &adl_features }, { INTEL_FAM6_METEORLAKE, &cnl_features }, { INTEL_FAM6_METEORLAKE_L, &cnl_features }, + { INTEL_FAM6_ARROWLAKE, &cnl_features }, { INTEL_FAM6_ATOM_SILVERMONT, &slv_features }, { INTEL_FAM6_ATOM_SILVERMONT_D, &slvd_features }, { INTEL_FAM6_ATOM_AIRMONT, &amt_features }, -- cgit v1.2.3 From 956dbd3de400a5665faf08a8588556db9c1bb56e Mon Sep 17 00:00:00 2001 From: Sumeet Pawnikar Date: Tue, 23 May 2023 17:46:45 +0530 Subject: tools/power/turbostat: Add initial support for LunarLake Add initial support for LunarLake platform. It shares the same features with CannonLake. Signed-off-by: Sumeet Pawnikar --- tools/power/x86/turbostat/turbostat.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 6c52cceae1d7..8a311d7272e7 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -871,6 +871,7 @@ static const struct platform_data turbostat_pdata[] = { { INTEL_FAM6_METEORLAKE, &cnl_features }, { INTEL_FAM6_METEORLAKE_L, &cnl_features }, { INTEL_FAM6_ARROWLAKE, &cnl_features }, + { INTEL_FAM6_LUNARLAKE_M, &cnl_features }, { INTEL_FAM6_ATOM_SILVERMONT, &slv_features }, { INTEL_FAM6_ATOM_SILVERMONT_D, &slvd_features }, { INTEL_FAM6_ATOM_AIRMONT, &amt_features }, -- cgit v1.2.3 From f2c1dba31133233697fc96e808c6005fc304a8e9 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 28 Jun 2023 09:40:53 -0400 Subject: tools/power/turbostat: bugfix "--show IPC" turbostat --show IPC displays "inf" for the IPC column turbostat was missing the explicit dependency of IPC on APERF, and thus neglected to collect APERF when only IPC was requested. typcial use: turbostat --quiet --show CPU,IPC Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 8a311d7272e7..5aa6598a40a9 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2202,7 +2202,8 @@ int delta_thread(struct thread_data *new, struct thread_data *old, struct core_d old->c1 = new->c1 - old->c1; - if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || soft_c1_residency_display(BIC_Avg_MHz)) { + if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || DO_BIC(BIC_IPC) + || soft_c1_residency_display(BIC_Avg_MHz)) { if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) { old->aperf = new->aperf - old->aperf; old->mperf = new->mperf - old->mperf; @@ -2724,7 +2725,8 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) retry: t->tsc = rdtsc(); /* we are running on local CPU of interest */ - if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || soft_c1_residency_display(BIC_Avg_MHz)) { + if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || DO_BIC(BIC_IPC) + || soft_c1_residency_display(BIC_Avg_MHz)) { unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time; /* -- cgit v1.2.3 From b8337e6a780dad9505f9d44da07c0a5c52fa0a04 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 7 Nov 2023 23:28:30 -0500 Subject: tools/power turbostat: version 2023.11.07 Turbostat features are now table-driven (Rui Zhang) Add support for some new platforms (Sumeet Pawnikar, Rui Zhang) Gracefully run in configs when CPUs are limited (Rui Zhang, Srinivas Pandruvada) misc minor fixes. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 5aa6598a40a9..7a334377f92b 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -6259,7 +6259,7 @@ int get_and_dump_counters(void) void print_version() { - fprintf(outf, "turbostat version 2023.03.17 - Len Brown \n"); + fprintf(outf, "turbostat version 2023.11.07 - Len Brown \n"); } #define COMMAND_LINE_SIZE 2048 -- cgit v1.2.3 From c3803203bc5ec910a3eb06172cf6fb368e0e4390 Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Mon, 16 Oct 2023 19:01:22 +0530 Subject: hv/hv_kvp_daemon: Some small fixes for handling NM keyfiles Some small fixes: - lets make sure we are not adding ipv4 addresses in ipv6 section in keyfile and vice versa. - ADDR_FAMILY_IPV6 is a bit in addr_family. Test that bit instead of checking the whole value of addr_family. - Some trivial fixes in hv_set_ifconfig.sh. These fixes are proposed after doing some internal testing at Red Hat. CC: Shradha Gupta CC: Saurabh Sengar Fixes: 42999c904612 ("hv/hv_kvp_daemon:Support for keyfile based connection profile") Signed-off-by: Ani Sinha Reviewed-by: Shradha Gupta Signed-off-by: Wei Liu Message-ID: <20231016133122.2419537-1-anisinha@redhat.com> --- tools/hv/hv_kvp_daemon.c | 20 ++++++++++++-------- tools/hv/hv_set_ifconfig.sh | 4 ++-- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 264eeb9c46a9..318e2dad27e0 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -1421,7 +1421,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) if (error) goto setval_error; - if (new_val->addr_family == ADDR_FAMILY_IPV6) { + if (new_val->addr_family & ADDR_FAMILY_IPV6) { error = fprintf(nmfile, "\n[ipv6]\n"); if (error < 0) goto setval_error; @@ -1455,14 +1455,18 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) if (error < 0) goto setval_error; - error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way); - if (error < 0) - goto setval_error; - - error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr); - if (error < 0) - goto setval_error; + /* we do not want ipv4 addresses in ipv6 section and vice versa */ + if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) { + error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way); + if (error < 0) + goto setval_error; + } + if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) { + error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr); + if (error < 0) + goto setval_error; + } fclose(nmfile); fclose(ifcfg_file); diff --git a/tools/hv/hv_set_ifconfig.sh b/tools/hv/hv_set_ifconfig.sh index ae5a7a8249a2..440a91b35823 100755 --- a/tools/hv/hv_set_ifconfig.sh +++ b/tools/hv/hv_set_ifconfig.sh @@ -53,7 +53,7 @@ # or "manual" if no boot-time protocol should be used) # # address1=ipaddr1/plen -# address=ipaddr2/plen +# address2=ipaddr2/plen # # gateway=gateway1;gateway2 # @@ -61,7 +61,7 @@ # # [ipv6] # address1=ipaddr1/plen -# address2=ipaddr1/plen +# address2=ipaddr2/plen # # gateway=gateway1;gateway2 # -- cgit v1.2.3 From 019b277b680f5b95135c042c78dd79318d8f9e3c Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Fri, 3 Nov 2023 23:23:41 +0500 Subject: selftests: mm: skip whole test instead of failure Some architectures don't support userfaultfd. Skip running the whole test on them instead of registering the failure. Link: https://lkml.kernel.org/r/20231103182343.2874015-1-usama.anjum@collabora.com Fixes: 46fd75d4a3c9 ("selftests: mm: add pagemap ioctl tests") Reported-by: Ryan Roberts Closes: https://lore.kernel.org/all/f8463381-2697-49e9-9460-9dc73452830d@arm.com Signed-off-by: Muhammad Usama Anjum Cc: Shuah Khan Signed-off-by: Andrew Morton --- tools/testing/selftests/mm/pagemap_ioctl.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c index 0161fb49fc6e..f8685a2ea07e 100644 --- a/tools/testing/selftests/mm/pagemap_ioctl.c +++ b/tools/testing/selftests/mm/pagemap_ioctl.c @@ -94,19 +94,19 @@ int init_uffd(void) uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY); if (uffd == -1) - ksft_exit_fail_msg("uffd syscall failed\n"); + return uffd; uffdio_api.api = UFFD_API; uffdio_api.features = UFFD_FEATURE_WP_UNPOPULATED | UFFD_FEATURE_WP_ASYNC | UFFD_FEATURE_WP_HUGETLBFS_SHMEM; if (ioctl(uffd, UFFDIO_API, &uffdio_api)) - ksft_exit_fail_msg("UFFDIO_API\n"); + return -1; if (!(uffdio_api.api & UFFDIO_REGISTER_MODE_WP) || !(uffdio_api.features & UFFD_FEATURE_WP_UNPOPULATED) || !(uffdio_api.features & UFFD_FEATURE_WP_ASYNC) || !(uffdio_api.features & UFFD_FEATURE_WP_HUGETLBFS_SHMEM)) - ksft_exit_fail_msg("UFFDIO_API error %llu\n", uffdio_api.api); + return -1; return 0; } @@ -1479,6 +1479,10 @@ int main(void) struct stat sbuf; ksft_print_header(); + + if (init_uffd()) + return ksft_exit_pass(); + ksft_set_plan(115); page_size = getpagesize(); @@ -1488,9 +1492,6 @@ int main(void) if (pagemap_fd < 0) return -EINVAL; - if (init_uffd()) - ksft_exit_fail_msg("uffd init failed\n"); - /* 1. Sanity testing */ sanity_tests_sd(); -- cgit v1.2.3 From 9297e5360c3bd777f95d5146dbeda7fb9ba4273a Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Fri, 3 Nov 2023 23:23:42 +0500 Subject: selftests: mm: fix some build warnings Fix build warnings: pagemap_ioctl.c:1154:38: warning: format `%s' expects a matching `char *' argument [-Wformat=] pagemap_ioctl.c:1162:51: warning: format `%ld' expects argument of type `long int', but argument 2 has type `int' [-Wformat=] pagemap_ioctl.c:1192:51: warning: format `%ld' expects argument of type `long int', but argument 2 has type `int' [-Wformat=] pagemap_ioctl.c:1600:51: warning: format `%ld' expects argument of type `long int', but argument 2 has type `int' [-Wformat=] pagemap_ioctl.c:1628:51: warning: format `%ld' expects argument of type `long int', but argument 2 has type `int' [-Wformat=] Link: https://lkml.kernel.org/r/20231103182343.2874015-2-usama.anjum@collabora.com Fixes: 46fd75d4a3c9 ("selftests: mm: add pagemap ioctl tests") Signed-off-by: Muhammad Usama Anjum Cc: Shuah Khan Cc: Ryan Roberts Signed-off-by: Andrew Morton --- tools/testing/selftests/mm/pagemap_ioctl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/mm/pagemap_ioctl.c b/tools/testing/selftests/mm/pagemap_ioctl.c index f8685a2ea07e..befab43719ba 100644 --- a/tools/testing/selftests/mm/pagemap_ioctl.c +++ b/tools/testing/selftests/mm/pagemap_ioctl.c @@ -1151,7 +1151,7 @@ int sanity_tests(void) /* 9. Memory mapped file */ fd = open(__FILE__, O_RDONLY); if (fd < 0) - ksft_exit_fail_msg("%s Memory mapped file\n"); + ksft_exit_fail_msg("%s Memory mapped file\n", __func__); ret = stat(__FILE__, &sbuf); if (ret < 0) @@ -1159,7 +1159,7 @@ int sanity_tests(void) fmem = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (fmem == MAP_FAILED) - ksft_exit_fail_msg("error nomem %ld %s\n", errno, strerror(errno)); + ksft_exit_fail_msg("error nomem %d %s\n", errno, strerror(errno)); tmp_buf = malloc(sbuf.st_size); memcpy(tmp_buf, fmem, sbuf.st_size); @@ -1189,7 +1189,7 @@ int sanity_tests(void) fmem = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (fmem == MAP_FAILED) - ksft_exit_fail_msg("error nomem %ld %s\n", errno, strerror(errno)); + ksft_exit_fail_msg("error nomem %d %s\n", errno, strerror(errno)); wp_init(fmem, buf_size); wp_addr_range(fmem, buf_size); @@ -1596,7 +1596,7 @@ int main(void) fmem = mmap(NULL, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (fmem == MAP_FAILED) - ksft_exit_fail_msg("error nomem %ld %s\n", errno, strerror(errno)); + ksft_exit_fail_msg("error nomem %d %s\n", errno, strerror(errno)); wp_init(fmem, sbuf.st_size); wp_addr_range(fmem, sbuf.st_size); @@ -1624,7 +1624,7 @@ int main(void) fmem = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (fmem == MAP_FAILED) - ksft_exit_fail_msg("error nomem %ld %s\n", errno, strerror(errno)); + ksft_exit_fail_msg("error nomem %d %s\n", errno, strerror(errno)); wp_init(fmem, buf_size); wp_addr_range(fmem, buf_size); -- cgit v1.2.3 From dd9b35efd719be242e227f9eebad1e50ea5c914f Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 3 Nov 2023 10:33:59 -0700 Subject: selftests/mm: restore number of hugepages The test mm `hugetlb_fault_after_madv` selftest needs one and only one huge page to run, thus it sets `/proc/sys/vm/nr_hugepages` to 1. The problem is that further tests require the previous number of hugepages allocated in order to succeed. Save the number of huge pages before changing it, and restore it once the test finishes, so, further tests could run successfully. Link: https://lkml.kernel.org/r/20231103173400.1608403-1-leitao@debian.org Fixes: 116d57303a05 ("selftests/mm: add a new test for madv and hugetlb") Signed-off-by: Breno Leitao Reported-by: Ryan Roberts Closes: https://lore.kernel.org/all/662df57e-47f1-4c15-9b84-f2f2d587fc5c@arm.com/ Signed-off-by: Andrew Morton --- tools/testing/selftests/mm/run_vmtests.sh | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh index cc16f6ca8533..00757445278e 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -223,9 +223,12 @@ CATEGORY="hugetlb" run_test ./hugepage-mremap CATEGORY="hugetlb" run_test ./hugepage-vmemmap CATEGORY="hugetlb" run_test ./hugetlb-madvise +nr_hugepages_tmp=$(cat /proc/sys/vm/nr_hugepages) # For this test, we need one and just one huge page echo 1 > /proc/sys/vm/nr_hugepages CATEGORY="hugetlb" run_test ./hugetlb_fault_after_madv +# Restore the previous number of huge pages, since further tests rely on it +echo "$nr_hugepages_tmp" > /proc/sys/vm/nr_hugepages if test_selected "hugetlb"; then echo "NOTE: These hugetlb tests provide minimal coverage. Use" -- cgit v1.2.3 From edf14544324dd036183fafe372fe5709708bdddd Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 3 Nov 2023 10:34:00 -0700 Subject: selftests/mm: add hugetlb_fault_after_madv to .gitignore commit 116d57303a05 ("selftests/mm: add a new test for madv and hugetlb") added a new test case, but, it didn't add the binary name in tools/testing/selftests/mm/.gitignore. Add hugetlb_fault_after_madv to tools/testing/selftests/mm/.gitignore. Link: https://lkml.kernel.org/r/20231103173400.1608403-2-leitao@debian.org Fixes: 116d57303a05 ("selftests/mm: add a new test for madv and hugetlb") Signed-off-by: Breno Leitao Reported-by: Ryan Roberts Closes: https://lore.kernel.org/all/662df57e-47f1-4c15-9b84-f2f2d587fc5c@arm.com/ Signed-off-by: Andrew Morton --- tools/testing/selftests/mm/.gitignore | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/testing/selftests/mm/.gitignore b/tools/testing/selftests/mm/.gitignore index cc920c79ff1c..4ff10ea61461 100644 --- a/tools/testing/selftests/mm/.gitignore +++ b/tools/testing/selftests/mm/.gitignore @@ -45,3 +45,4 @@ mdwe_test gup_longterm mkdirty va_high_addr_switch +hugetlb_fault_after_madv -- cgit v1.2.3 From 75a50c4f5b957a34dedb7c8cce52b582a9162828 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 16 Nov 2023 18:01:41 +0100 Subject: kselftest: rtnetlink: fix ip route command typo The blamed commit below introduced a typo causing 'gretap' test-case failures: ./rtnetlink.sh -t kci_test_gretap -v COMMAND: ip link add name test-dummy0 type dummy COMMAND: ip link set test-dummy0 up COMMAND: ip netns add testns COMMAND: ip link help gretap 2>&1 | grep -q '^Usage:' COMMAND: ip -netns testns link add dev gretap00 type gretap seq key 102 local 172.16.1.100 remote 172.16.1.200 COMMAND: ip -netns testns addr add dev gretap00 10.1.1.100/24 COMMAND: ip -netns testns link set dev gretap00 ups Error: either "dev" is duplicate, or "ups" is a garbage. COMMAND: ip -netns testns link del gretap00 COMMAND: ip -netns testns link add dev gretap00 type gretap external COMMAND: ip -netns testns link del gretap00 FAIL: gretap Fix it by using the correct keyword. Fixes: 9c2a19f71515 ("kselftest: rtnetlink.sh: add verbose flag") Signed-off-by: Paolo Abeni Reviewed-by: Hangbin Liu Signed-off-by: David S. Miller --- tools/testing/selftests/net/rtnetlink.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh index 5f2b3f6c0d74..38be9706c45f 100755 --- a/tools/testing/selftests/net/rtnetlink.sh +++ b/tools/testing/selftests/net/rtnetlink.sh @@ -859,7 +859,7 @@ kci_test_gretap() run_cmd ip -netns "$testns" addr add dev "$DEV_NS" 10.1.1.100/24 - run_cmd ip -netns "$testns" link set dev $DEV_NS ups + run_cmd ip -netns "$testns" link set dev $DEV_NS up run_cmd ip -netns "$testns" link del "$DEV_NS" # test external mode -- cgit v1.2.3 From eee82da79f036bb49ff80d3088b9530e3c2e57eb Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 14 Nov 2023 01:42:19 +0100 Subject: selftests/bpf: De-veth-ize the tc_redirect test case No functional changes to the test case, but just renaming various functions, variables, etc, to remove veth part of their name for making it more generic and reusable later on (e.g. for netkit). Signed-off-by: Daniel Borkmann Acked-by: Stanislav Fomichev Reviewed-by: Nikolay Aleksandrov Link: https://lore.kernel.org/r/20231114004220.6495-8-daniel@iogearbox.net Signed-off-by: Martin KaFai Lau --- .../testing/selftests/bpf/prog_tests/tc_redirect.c | 263 +++++++++++---------- 1 file changed, 137 insertions(+), 126 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c index 6ee22c3b251a..407ff4e9bc78 100644 --- a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c +++ b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c @@ -110,11 +110,16 @@ static void netns_setup_namespaces_nofail(const char *verb) } } +enum dev_mode { + MODE_VETH, +}; + struct netns_setup_result { - int ifindex_veth_src; - int ifindex_veth_src_fwd; - int ifindex_veth_dst; - int ifindex_veth_dst_fwd; + enum dev_mode dev_mode; + int ifindex_src; + int ifindex_src_fwd; + int ifindex_dst; + int ifindex_dst_fwd; }; static int get_ifaddr(const char *name, char *ifaddr) @@ -140,55 +145,59 @@ static int get_ifaddr(const char *name, char *ifaddr) static int netns_setup_links_and_routes(struct netns_setup_result *result) { struct nstoken *nstoken = NULL; - char veth_src_fwd_addr[IFADDR_STR_LEN+1] = {}; + char src_fwd_addr[IFADDR_STR_LEN+1] = {}; - SYS(fail, "ip link add veth_src type veth peer name veth_src_fwd"); - SYS(fail, "ip link add veth_dst type veth peer name veth_dst_fwd"); + if (result->dev_mode == MODE_VETH) { + SYS(fail, "ip link add src type veth peer name src_fwd"); + SYS(fail, "ip link add dst type veth peer name dst_fwd"); - SYS(fail, "ip link set veth_dst_fwd address " MAC_DST_FWD); - SYS(fail, "ip link set veth_dst address " MAC_DST); + SYS(fail, "ip link set dst_fwd address " MAC_DST_FWD); + SYS(fail, "ip link set dst address " MAC_DST); + } - if (get_ifaddr("veth_src_fwd", veth_src_fwd_addr)) + if (get_ifaddr("src_fwd", src_fwd_addr)) goto fail; - result->ifindex_veth_src = if_nametoindex("veth_src"); - if (!ASSERT_GT(result->ifindex_veth_src, 0, "ifindex_veth_src")) + result->ifindex_src = if_nametoindex("src"); + if (!ASSERT_GT(result->ifindex_src, 0, "ifindex_src")) goto fail; - result->ifindex_veth_src_fwd = if_nametoindex("veth_src_fwd"); - if (!ASSERT_GT(result->ifindex_veth_src_fwd, 0, "ifindex_veth_src_fwd")) + result->ifindex_src_fwd = if_nametoindex("src_fwd"); + if (!ASSERT_GT(result->ifindex_src_fwd, 0, "ifindex_src_fwd")) goto fail; - result->ifindex_veth_dst = if_nametoindex("veth_dst"); - if (!ASSERT_GT(result->ifindex_veth_dst, 0, "ifindex_veth_dst")) + result->ifindex_dst = if_nametoindex("dst"); + if (!ASSERT_GT(result->ifindex_dst, 0, "ifindex_dst")) goto fail; - result->ifindex_veth_dst_fwd = if_nametoindex("veth_dst_fwd"); - if (!ASSERT_GT(result->ifindex_veth_dst_fwd, 0, "ifindex_veth_dst_fwd")) + result->ifindex_dst_fwd = if_nametoindex("dst_fwd"); + if (!ASSERT_GT(result->ifindex_dst_fwd, 0, "ifindex_dst_fwd")) goto fail; - SYS(fail, "ip link set veth_src netns " NS_SRC); - SYS(fail, "ip link set veth_src_fwd netns " NS_FWD); - SYS(fail, "ip link set veth_dst_fwd netns " NS_FWD); - SYS(fail, "ip link set veth_dst netns " NS_DST); + SYS(fail, "ip link set src netns " NS_SRC); + SYS(fail, "ip link set src_fwd netns " NS_FWD); + SYS(fail, "ip link set dst_fwd netns " NS_FWD); + SYS(fail, "ip link set dst netns " NS_DST); /** setup in 'src' namespace */ nstoken = open_netns(NS_SRC); if (!ASSERT_OK_PTR(nstoken, "setns src")) goto fail; - SYS(fail, "ip addr add " IP4_SRC "/32 dev veth_src"); - SYS(fail, "ip addr add " IP6_SRC "/128 dev veth_src nodad"); - SYS(fail, "ip link set dev veth_src up"); + SYS(fail, "ip addr add " IP4_SRC "/32 dev src"); + SYS(fail, "ip addr add " IP6_SRC "/128 dev src nodad"); + SYS(fail, "ip link set dev src up"); - SYS(fail, "ip route add " IP4_DST "/32 dev veth_src scope global"); - SYS(fail, "ip route add " IP4_NET "/16 dev veth_src scope global"); - SYS(fail, "ip route add " IP6_DST "/128 dev veth_src scope global"); + SYS(fail, "ip route add " IP4_DST "/32 dev src scope global"); + SYS(fail, "ip route add " IP4_NET "/16 dev src scope global"); + SYS(fail, "ip route add " IP6_DST "/128 dev src scope global"); - SYS(fail, "ip neigh add " IP4_DST " dev veth_src lladdr %s", - veth_src_fwd_addr); - SYS(fail, "ip neigh add " IP6_DST " dev veth_src lladdr %s", - veth_src_fwd_addr); + if (result->dev_mode == MODE_VETH) { + SYS(fail, "ip neigh add " IP4_DST " dev src lladdr %s", + src_fwd_addr); + SYS(fail, "ip neigh add " IP6_DST " dev src lladdr %s", + src_fwd_addr); + } close_netns(nstoken); @@ -201,15 +210,15 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result) * needs v4 one in order to start ARP probing. IP4_NET route is added * to the endpoints so that the ARP processing will reply. */ - SYS(fail, "ip addr add " IP4_SLL "/32 dev veth_src_fwd"); - SYS(fail, "ip addr add " IP4_DLL "/32 dev veth_dst_fwd"); - SYS(fail, "ip link set dev veth_src_fwd up"); - SYS(fail, "ip link set dev veth_dst_fwd up"); + SYS(fail, "ip addr add " IP4_SLL "/32 dev src_fwd"); + SYS(fail, "ip addr add " IP4_DLL "/32 dev dst_fwd"); + SYS(fail, "ip link set dev src_fwd up"); + SYS(fail, "ip link set dev dst_fwd up"); - SYS(fail, "ip route add " IP4_SRC "/32 dev veth_src_fwd scope global"); - SYS(fail, "ip route add " IP6_SRC "/128 dev veth_src_fwd scope global"); - SYS(fail, "ip route add " IP4_DST "/32 dev veth_dst_fwd scope global"); - SYS(fail, "ip route add " IP6_DST "/128 dev veth_dst_fwd scope global"); + SYS(fail, "ip route add " IP4_SRC "/32 dev src_fwd scope global"); + SYS(fail, "ip route add " IP6_SRC "/128 dev src_fwd scope global"); + SYS(fail, "ip route add " IP4_DST "/32 dev dst_fwd scope global"); + SYS(fail, "ip route add " IP6_DST "/128 dev dst_fwd scope global"); close_netns(nstoken); @@ -218,16 +227,18 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result) if (!ASSERT_OK_PTR(nstoken, "setns dst")) goto fail; - SYS(fail, "ip addr add " IP4_DST "/32 dev veth_dst"); - SYS(fail, "ip addr add " IP6_DST "/128 dev veth_dst nodad"); - SYS(fail, "ip link set dev veth_dst up"); + SYS(fail, "ip addr add " IP4_DST "/32 dev dst"); + SYS(fail, "ip addr add " IP6_DST "/128 dev dst nodad"); + SYS(fail, "ip link set dev dst up"); - SYS(fail, "ip route add " IP4_SRC "/32 dev veth_dst scope global"); - SYS(fail, "ip route add " IP4_NET "/16 dev veth_dst scope global"); - SYS(fail, "ip route add " IP6_SRC "/128 dev veth_dst scope global"); + SYS(fail, "ip route add " IP4_SRC "/32 dev dst scope global"); + SYS(fail, "ip route add " IP4_NET "/16 dev dst scope global"); + SYS(fail, "ip route add " IP6_SRC "/128 dev dst scope global"); - SYS(fail, "ip neigh add " IP4_SRC " dev veth_dst lladdr " MAC_DST_FWD); - SYS(fail, "ip neigh add " IP6_SRC " dev veth_dst lladdr " MAC_DST_FWD); + if (result->dev_mode == MODE_VETH) { + SYS(fail, "ip neigh add " IP4_SRC " dev dst lladdr " MAC_DST_FWD); + SYS(fail, "ip neigh add " IP6_SRC " dev dst lladdr " MAC_DST_FWD); + } close_netns(nstoken); @@ -293,23 +304,23 @@ static int netns_load_bpf(const struct bpf_program *src_prog, const struct bpf_program *chk_prog, const struct netns_setup_result *setup_result) { - LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src_fwd); - LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd); + LIBBPF_OPTS(bpf_tc_hook, qdisc_src_fwd); + LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd); int err; - /* tc qdisc add dev veth_src_fwd clsact */ - QDISC_CLSACT_CREATE(&qdisc_veth_src_fwd, setup_result->ifindex_veth_src_fwd); - /* tc filter add dev veth_src_fwd ingress bpf da src_prog */ - XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS, src_prog, 0); - /* tc filter add dev veth_src_fwd egress bpf da chk_prog */ - XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS, chk_prog, 0); + /* tc qdisc add dev src_fwd clsact */ + QDISC_CLSACT_CREATE(&qdisc_src_fwd, setup_result->ifindex_src_fwd); + /* tc filter add dev src_fwd ingress bpf da src_prog */ + XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS, src_prog, 0); + /* tc filter add dev src_fwd egress bpf da chk_prog */ + XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS, chk_prog, 0); - /* tc qdisc add dev veth_dst_fwd clsact */ - QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd); - /* tc filter add dev veth_dst_fwd ingress bpf da dst_prog */ - XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS, dst_prog, 0); - /* tc filter add dev veth_dst_fwd egress bpf da chk_prog */ - XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS, chk_prog, 0); + /* tc qdisc add dev dst_fwd clsact */ + QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd); + /* tc filter add dev dst_fwd ingress bpf da dst_prog */ + XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS, dst_prog, 0); + /* tc filter add dev dst_fwd egress bpf da chk_prog */ + XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS, chk_prog, 0); return 0; fail: @@ -539,10 +550,10 @@ done: static int netns_load_dtime_bpf(struct test_tc_dtime *skel, const struct netns_setup_result *setup_result) { - LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src_fwd); - LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd); - LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_src); - LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst); + LIBBPF_OPTS(bpf_tc_hook, qdisc_src_fwd); + LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd); + LIBBPF_OPTS(bpf_tc_hook, qdisc_src); + LIBBPF_OPTS(bpf_tc_hook, qdisc_dst); struct nstoken *nstoken; int err; @@ -550,58 +561,58 @@ static int netns_load_dtime_bpf(struct test_tc_dtime *skel, nstoken = open_netns(NS_SRC); if (!ASSERT_OK_PTR(nstoken, "setns " NS_SRC)) return -1; - /* tc qdisc add dev veth_src clsact */ - QDISC_CLSACT_CREATE(&qdisc_veth_src, setup_result->ifindex_veth_src); - /* tc filter add dev veth_src ingress bpf da ingress_host */ - XGRESS_FILTER_ADD(&qdisc_veth_src, BPF_TC_INGRESS, skel->progs.ingress_host, 0); - /* tc filter add dev veth_src egress bpf da egress_host */ - XGRESS_FILTER_ADD(&qdisc_veth_src, BPF_TC_EGRESS, skel->progs.egress_host, 0); + /* tc qdisc add dev src clsact */ + QDISC_CLSACT_CREATE(&qdisc_src, setup_result->ifindex_src); + /* tc filter add dev src ingress bpf da ingress_host */ + XGRESS_FILTER_ADD(&qdisc_src, BPF_TC_INGRESS, skel->progs.ingress_host, 0); + /* tc filter add dev src egress bpf da egress_host */ + XGRESS_FILTER_ADD(&qdisc_src, BPF_TC_EGRESS, skel->progs.egress_host, 0); close_netns(nstoken); /* setup ns_dst tc progs */ nstoken = open_netns(NS_DST); if (!ASSERT_OK_PTR(nstoken, "setns " NS_DST)) return -1; - /* tc qdisc add dev veth_dst clsact */ - QDISC_CLSACT_CREATE(&qdisc_veth_dst, setup_result->ifindex_veth_dst); - /* tc filter add dev veth_dst ingress bpf da ingress_host */ - XGRESS_FILTER_ADD(&qdisc_veth_dst, BPF_TC_INGRESS, skel->progs.ingress_host, 0); - /* tc filter add dev veth_dst egress bpf da egress_host */ - XGRESS_FILTER_ADD(&qdisc_veth_dst, BPF_TC_EGRESS, skel->progs.egress_host, 0); + /* tc qdisc add dev dst clsact */ + QDISC_CLSACT_CREATE(&qdisc_dst, setup_result->ifindex_dst); + /* tc filter add dev dst ingress bpf da ingress_host */ + XGRESS_FILTER_ADD(&qdisc_dst, BPF_TC_INGRESS, skel->progs.ingress_host, 0); + /* tc filter add dev dst egress bpf da egress_host */ + XGRESS_FILTER_ADD(&qdisc_dst, BPF_TC_EGRESS, skel->progs.egress_host, 0); close_netns(nstoken); /* setup ns_fwd tc progs */ nstoken = open_netns(NS_FWD); if (!ASSERT_OK_PTR(nstoken, "setns " NS_FWD)) return -1; - /* tc qdisc add dev veth_dst_fwd clsact */ - QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd); - /* tc filter add dev veth_dst_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */ - XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS, + /* tc qdisc add dev dst_fwd clsact */ + QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd); + /* tc filter add dev dst_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */ + XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS, skel->progs.ingress_fwdns_prio100, 100); - /* tc filter add dev veth_dst_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */ - XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS, + /* tc filter add dev dst_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */ + XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS, skel->progs.ingress_fwdns_prio101, 101); - /* tc filter add dev veth_dst_fwd egress prio 100 bpf da egress_fwdns_prio100 */ - XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS, + /* tc filter add dev dst_fwd egress prio 100 bpf da egress_fwdns_prio100 */ + XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS, skel->progs.egress_fwdns_prio100, 100); - /* tc filter add dev veth_dst_fwd egress prio 101 bpf da egress_fwdns_prio101 */ - XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS, + /* tc filter add dev dst_fwd egress prio 101 bpf da egress_fwdns_prio101 */ + XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS, skel->progs.egress_fwdns_prio101, 101); - /* tc qdisc add dev veth_src_fwd clsact */ - QDISC_CLSACT_CREATE(&qdisc_veth_src_fwd, setup_result->ifindex_veth_src_fwd); - /* tc filter add dev veth_src_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */ - XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS, + /* tc qdisc add dev src_fwd clsact */ + QDISC_CLSACT_CREATE(&qdisc_src_fwd, setup_result->ifindex_src_fwd); + /* tc filter add dev src_fwd ingress prio 100 bpf da ingress_fwdns_prio100 */ + XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS, skel->progs.ingress_fwdns_prio100, 100); - /* tc filter add dev veth_src_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */ - XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_INGRESS, + /* tc filter add dev src_fwd ingress prio 101 bpf da ingress_fwdns_prio101 */ + XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_INGRESS, skel->progs.ingress_fwdns_prio101, 101); - /* tc filter add dev veth_src_fwd egress prio 100 bpf da egress_fwdns_prio100 */ - XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS, + /* tc filter add dev src_fwd egress prio 100 bpf da egress_fwdns_prio100 */ + XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS, skel->progs.egress_fwdns_prio100, 100); - /* tc filter add dev veth_src_fwd egress prio 101 bpf da egress_fwdns_prio101 */ - XGRESS_FILTER_ADD(&qdisc_veth_src_fwd, BPF_TC_EGRESS, + /* tc filter add dev src_fwd egress prio 101 bpf da egress_fwdns_prio101 */ + XGRESS_FILTER_ADD(&qdisc_src_fwd, BPF_TC_EGRESS, skel->progs.egress_fwdns_prio101, 101); close_netns(nstoken); return 0; @@ -777,8 +788,8 @@ static void test_tc_redirect_dtime(struct netns_setup_result *setup_result) if (!ASSERT_OK_PTR(skel, "test_tc_dtime__open")) return; - skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd; - skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd; + skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd; + skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd; err = test_tc_dtime__load(skel); if (!ASSERT_OK(err, "test_tc_dtime__load")) @@ -868,8 +879,8 @@ static void test_tc_redirect_neigh(struct netns_setup_result *setup_result) if (!ASSERT_OK_PTR(skel, "test_tc_neigh__open")) goto done; - skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd; - skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd; + skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd; + skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd; err = test_tc_neigh__load(skel); if (!ASSERT_OK(err, "test_tc_neigh__load")) @@ -904,8 +915,8 @@ static void test_tc_redirect_peer(struct netns_setup_result *setup_result) if (!ASSERT_OK_PTR(skel, "test_tc_peer__open")) goto done; - skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd; - skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd; + skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd; + skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd; err = test_tc_peer__load(skel); if (!ASSERT_OK(err, "test_tc_peer__load")) @@ -996,7 +1007,7 @@ static int tun_relay_loop(int src_fd, int target_fd) static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result) { LIBBPF_OPTS(bpf_tc_hook, qdisc_tun_fwd); - LIBBPF_OPTS(bpf_tc_hook, qdisc_veth_dst_fwd); + LIBBPF_OPTS(bpf_tc_hook, qdisc_dst_fwd); struct test_tc_peer *skel = NULL; struct nstoken *nstoken = NULL; int err; @@ -1045,7 +1056,7 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result) goto fail; skel->rodata->IFINDEX_SRC = ifindex; - skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd; + skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd; err = test_tc_peer__load(skel); if (!ASSERT_OK(err, "test_tc_peer__load")) @@ -1053,19 +1064,19 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result) /* Load "tc_src_l3" to the tun_fwd interface to redirect packets * towards dst, and "tc_dst" to redirect packets - * and "tc_chk" on veth_dst_fwd to drop non-redirected packets. + * and "tc_chk" on dst_fwd to drop non-redirected packets. */ /* tc qdisc add dev tun_fwd clsact */ QDISC_CLSACT_CREATE(&qdisc_tun_fwd, ifindex); /* tc filter add dev tun_fwd ingress bpf da tc_src_l3 */ XGRESS_FILTER_ADD(&qdisc_tun_fwd, BPF_TC_INGRESS, skel->progs.tc_src_l3, 0); - /* tc qdisc add dev veth_dst_fwd clsact */ - QDISC_CLSACT_CREATE(&qdisc_veth_dst_fwd, setup_result->ifindex_veth_dst_fwd); - /* tc filter add dev veth_dst_fwd ingress bpf da tc_dst_l3 */ - XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_INGRESS, skel->progs.tc_dst_l3, 0); - /* tc filter add dev veth_dst_fwd egress bpf da tc_chk */ - XGRESS_FILTER_ADD(&qdisc_veth_dst_fwd, BPF_TC_EGRESS, skel->progs.tc_chk, 0); + /* tc qdisc add dev dst_fwd clsact */ + QDISC_CLSACT_CREATE(&qdisc_dst_fwd, setup_result->ifindex_dst_fwd); + /* tc filter add dev dst_fwd ingress bpf da tc_dst_l3 */ + XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_INGRESS, skel->progs.tc_dst_l3, 0); + /* tc filter add dev dst_fwd egress bpf da tc_chk */ + XGRESS_FILTER_ADD(&qdisc_dst_fwd, BPF_TC_EGRESS, skel->progs.tc_chk, 0); /* Setup route and neigh tables */ SYS(fail, "ip -netns " NS_SRC " addr add dev tun_src " IP4_TUN_SRC "/24"); @@ -1074,17 +1085,17 @@ static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result) SYS(fail, "ip -netns " NS_SRC " addr add dev tun_src " IP6_TUN_SRC "/64 nodad"); SYS(fail, "ip -netns " NS_FWD " addr add dev tun_fwd " IP6_TUN_FWD "/64 nodad"); - SYS(fail, "ip -netns " NS_SRC " route del " IP4_DST "/32 dev veth_src scope global"); + SYS(fail, "ip -netns " NS_SRC " route del " IP4_DST "/32 dev src scope global"); SYS(fail, "ip -netns " NS_SRC " route add " IP4_DST "/32 via " IP4_TUN_FWD " dev tun_src scope global"); - SYS(fail, "ip -netns " NS_DST " route add " IP4_TUN_SRC "/32 dev veth_dst scope global"); - SYS(fail, "ip -netns " NS_SRC " route del " IP6_DST "/128 dev veth_src scope global"); + SYS(fail, "ip -netns " NS_DST " route add " IP4_TUN_SRC "/32 dev dst scope global"); + SYS(fail, "ip -netns " NS_SRC " route del " IP6_DST "/128 dev src scope global"); SYS(fail, "ip -netns " NS_SRC " route add " IP6_DST "/128 via " IP6_TUN_FWD " dev tun_src scope global"); - SYS(fail, "ip -netns " NS_DST " route add " IP6_TUN_SRC "/128 dev veth_dst scope global"); + SYS(fail, "ip -netns " NS_DST " route add " IP6_TUN_SRC "/128 dev dst scope global"); - SYS(fail, "ip -netns " NS_DST " neigh add " IP4_TUN_SRC " dev veth_dst lladdr " MAC_DST_FWD); - SYS(fail, "ip -netns " NS_DST " neigh add " IP6_TUN_SRC " dev veth_dst lladdr " MAC_DST_FWD); + SYS(fail, "ip -netns " NS_DST " neigh add " IP4_TUN_SRC " dev dst lladdr " MAC_DST_FWD); + SYS(fail, "ip -netns " NS_DST " neigh add " IP6_TUN_SRC " dev dst lladdr " MAC_DST_FWD); if (!ASSERT_OK(set_forwarding(false), "disable forwarding")) goto fail; @@ -1106,9 +1117,9 @@ fail: close_netns(nstoken); } -#define RUN_TEST(name) \ +#define RUN_TEST(name, mode) \ ({ \ - struct netns_setup_result setup_result; \ + struct netns_setup_result setup_result = { .dev_mode = mode, }; \ if (test__start_subtest(#name)) \ if (ASSERT_OK(netns_setup_namespaces("add"), "setup namespaces")) { \ if (ASSERT_OK(netns_setup_links_and_routes(&setup_result), \ @@ -1122,11 +1133,11 @@ static void *test_tc_redirect_run_tests(void *arg) { netns_setup_namespaces_nofail("delete"); - RUN_TEST(tc_redirect_peer); - RUN_TEST(tc_redirect_peer_l3); - RUN_TEST(tc_redirect_neigh); - RUN_TEST(tc_redirect_neigh_fib); - RUN_TEST(tc_redirect_dtime); + RUN_TEST(tc_redirect_peer, MODE_VETH); + RUN_TEST(tc_redirect_peer_l3, MODE_VETH); + RUN_TEST(tc_redirect_neigh, MODE_VETH); + RUN_TEST(tc_redirect_neigh_fib, MODE_VETH); + RUN_TEST(tc_redirect_dtime, MODE_VETH); return NULL; } -- cgit v1.2.3 From adfeae2d243d9e5b83d094af481d189156b11779 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 14 Nov 2023 01:42:20 +0100 Subject: selftests/bpf: Add netkit to tc_redirect selftest Extend the existing tc_redirect selftest to also cover netkit devices for exercising the bpf_redirect_peer() code paths, so that we have both veth as well as netkit covered, all tests still pass after this change. Signed-off-by: Daniel Borkmann Acked-by: Stanislav Fomichev Reviewed-by: Nikolay Aleksandrov Link: https://lore.kernel.org/r/20231114004220.6495-9-daniel@iogearbox.net Signed-off-by: Martin KaFai Lau --- .../testing/selftests/bpf/prog_tests/tc_redirect.c | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c index 407ff4e9bc78..518f143c5b0f 100644 --- a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c +++ b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c @@ -24,6 +24,7 @@ #include "test_progs.h" #include "network_helpers.h" +#include "netlink_helpers.h" #include "test_tc_neigh_fib.skel.h" #include "test_tc_neigh.skel.h" #include "test_tc_peer.skel.h" @@ -112,6 +113,7 @@ static void netns_setup_namespaces_nofail(const char *verb) enum dev_mode { MODE_VETH, + MODE_NETKIT, }; struct netns_setup_result { @@ -142,10 +144,51 @@ static int get_ifaddr(const char *name, char *ifaddr) return 0; } +static int create_netkit(int mode, char *prim, char *peer) +{ + struct rtattr *linkinfo, *data, *peer_info; + struct rtnl_handle rth = { .fd = -1 }; + const char *type = "netkit"; + struct { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[1024]; + } req = {}; + int err; + + err = rtnl_open(&rth, 0); + if (!ASSERT_OK(err, "open_rtnetlink")) + return err; + + memset(&req, 0, sizeof(req)); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + req.n.nlmsg_type = RTM_NEWLINK; + req.i.ifi_family = AF_UNSPEC; + + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, prim, strlen(prim)); + linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO); + addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type)); + data = addattr_nest(&req.n, sizeof(req), IFLA_INFO_DATA); + addattr32(&req.n, sizeof(req), IFLA_NETKIT_MODE, mode); + peer_info = addattr_nest(&req.n, sizeof(req), IFLA_NETKIT_PEER_INFO); + req.n.nlmsg_len += sizeof(struct ifinfomsg); + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, peer, strlen(peer)); + addattr_nest_end(&req.n, peer_info); + addattr_nest_end(&req.n, data); + addattr_nest_end(&req.n, linkinfo); + + err = rtnl_talk(&rth, &req.n, NULL); + ASSERT_OK(err, "talk_rtnetlink"); + rtnl_close(&rth); + return err; +} + static int netns_setup_links_and_routes(struct netns_setup_result *result) { struct nstoken *nstoken = NULL; char src_fwd_addr[IFADDR_STR_LEN+1] = {}; + int err; if (result->dev_mode == MODE_VETH) { SYS(fail, "ip link add src type veth peer name src_fwd"); @@ -153,6 +196,13 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result) SYS(fail, "ip link set dst_fwd address " MAC_DST_FWD); SYS(fail, "ip link set dst address " MAC_DST); + } else if (result->dev_mode == MODE_NETKIT) { + err = create_netkit(NETKIT_L3, "src", "src_fwd"); + if (!ASSERT_OK(err, "create_ifindex_src")) + goto fail; + err = create_netkit(NETKIT_L3, "dst", "dst_fwd"); + if (!ASSERT_OK(err, "create_ifindex_dst")) + goto fail; } if (get_ifaddr("src_fwd", src_fwd_addr)) @@ -1134,7 +1184,9 @@ static void *test_tc_redirect_run_tests(void *arg) netns_setup_namespaces_nofail("delete"); RUN_TEST(tc_redirect_peer, MODE_VETH); + RUN_TEST(tc_redirect_peer, MODE_NETKIT); RUN_TEST(tc_redirect_peer_l3, MODE_VETH); + RUN_TEST(tc_redirect_peer_l3, MODE_NETKIT); RUN_TEST(tc_redirect_neigh, MODE_VETH); RUN_TEST(tc_redirect_neigh_fib, MODE_VETH); RUN_TEST(tc_redirect_dtime, MODE_VETH); -- cgit v1.2.3 From 977bc146d4eb7070118d8a974919b33bb52732b4 Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 21 Nov 2023 04:06:51 +0200 Subject: selftests/bpf: track tcp payload offset as scalar in xdp_synproxy This change prepares syncookie_{tc,xdp} for update in callbakcs verification logic. To allow bpf_loop() verification converge when multiple callback itreations are considered: - track offset inside TCP payload explicitly, not as a part of the pointer; - make sure that offset does not exceed MAX_PACKET_OFF enforced by verifier; - make sure that offset is tracked as unbound scalar between iterations, otherwise verifier won't be able infer that bpf_loop callback reaches identical states. Acked-by: Andrii Nakryiko Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20231121020701.26440-2-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/progs/xdp_synproxy_kern.c | 84 +++++++++++++--------- 1 file changed, 52 insertions(+), 32 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c b/tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c index e959336c7a73..80f620602d50 100644 --- a/tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c +++ b/tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c @@ -53,6 +53,8 @@ #define DEFAULT_TTL 64 #define MAX_ALLOWED_PORTS 8 +#define MAX_PACKET_OFF 0xffff + #define swap(a, b) \ do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) @@ -183,63 +185,76 @@ static __always_inline __u32 tcp_clock_ms(void) } struct tcpopt_context { - __u8 *ptr; - __u8 *end; + void *data; void *data_end; __be32 *tsecr; __u8 wscale; bool option_timestamp; bool option_sack; + __u32 off; }; -static int tscookie_tcpopt_parse(struct tcpopt_context *ctx) +static __always_inline u8 *next(struct tcpopt_context *ctx, __u32 sz) { - __u8 opcode, opsize; + __u64 off = ctx->off; + __u8 *data; - if (ctx->ptr >= ctx->end) - return 1; - if (ctx->ptr >= ctx->data_end) - return 1; + /* Verifier forbids access to packet when offset exceeds MAX_PACKET_OFF */ + if (off > MAX_PACKET_OFF - sz) + return NULL; - opcode = ctx->ptr[0]; + data = ctx->data + off; + barrier_var(data); + if (data + sz >= ctx->data_end) + return NULL; - if (opcode == TCPOPT_EOL) - return 1; - if (opcode == TCPOPT_NOP) { - ++ctx->ptr; - return 0; - } + ctx->off += sz; + return data; +} - if (ctx->ptr + 1 >= ctx->end) - return 1; - if (ctx->ptr + 1 >= ctx->data_end) +static int tscookie_tcpopt_parse(struct tcpopt_context *ctx) +{ + __u8 *opcode, *opsize, *wscale, *tsecr; + __u32 off = ctx->off; + + opcode = next(ctx, 1); + if (!opcode) return 1; - opsize = ctx->ptr[1]; - if (opsize < 2) + + if (*opcode == TCPOPT_EOL) return 1; + if (*opcode == TCPOPT_NOP) + return 0; - if (ctx->ptr + opsize > ctx->end) + opsize = next(ctx, 1); + if (!opsize || *opsize < 2) return 1; - switch (opcode) { + switch (*opcode) { case TCPOPT_WINDOW: - if (opsize == TCPOLEN_WINDOW && ctx->ptr + TCPOLEN_WINDOW <= ctx->data_end) - ctx->wscale = ctx->ptr[2] < TCP_MAX_WSCALE ? ctx->ptr[2] : TCP_MAX_WSCALE; + wscale = next(ctx, 1); + if (!wscale) + return 1; + if (*opsize == TCPOLEN_WINDOW) + ctx->wscale = *wscale < TCP_MAX_WSCALE ? *wscale : TCP_MAX_WSCALE; break; case TCPOPT_TIMESTAMP: - if (opsize == TCPOLEN_TIMESTAMP && ctx->ptr + TCPOLEN_TIMESTAMP <= ctx->data_end) { + tsecr = next(ctx, 4); + if (!tsecr) + return 1; + if (*opsize == TCPOLEN_TIMESTAMP) { ctx->option_timestamp = true; /* Client's tsval becomes our tsecr. */ - *ctx->tsecr = get_unaligned((__be32 *)(ctx->ptr + 2)); + *ctx->tsecr = get_unaligned((__be32 *)tsecr); } break; case TCPOPT_SACK_PERM: - if (opsize == TCPOLEN_SACK_PERM) + if (*opsize == TCPOLEN_SACK_PERM) ctx->option_sack = true; break; } - ctx->ptr += opsize; + ctx->off = off + *opsize; return 0; } @@ -256,16 +271,21 @@ static int tscookie_tcpopt_parse_batch(__u32 index, void *context) static __always_inline bool tscookie_init(struct tcphdr *tcp_header, __u16 tcp_len, __be32 *tsval, - __be32 *tsecr, void *data_end) + __be32 *tsecr, void *data, void *data_end) { struct tcpopt_context loop_ctx = { - .ptr = (__u8 *)(tcp_header + 1), - .end = (__u8 *)tcp_header + tcp_len, + .data = data, .data_end = data_end, .tsecr = tsecr, .wscale = TS_OPT_WSCALE_MASK, .option_timestamp = false, .option_sack = false, + /* Note: currently verifier would track .off as unbound scalar. + * In case if verifier would at some point get smarter and + * compute bounded value for this var, beware that it might + * hinder bpf_loop() convergence validation. + */ + .off = (__u8 *)(tcp_header + 1) - (__u8 *)data, }; u32 cookie; @@ -635,7 +655,7 @@ static __always_inline int syncookie_handle_syn(struct header_pointers *hdr, cookie = (__u32)value; if (tscookie_init((void *)hdr->tcp, hdr->tcp_len, - &tsopt_buf[0], &tsopt_buf[1], data_end)) + &tsopt_buf[0], &tsopt_buf[1], data, data_end)) tsopt = tsopt_buf; /* Check that there is enough space for a SYNACK. It also covers -- cgit v1.2.3 From 87eb0152bcc102ecbda866978f4e54db5a3be1ef Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 21 Nov 2023 04:06:52 +0200 Subject: selftests/bpf: track string payload offset as scalar in strobemeta This change prepares strobemeta for update in callbacks verification logic. To allow bpf_loop() verification converge when multiple callback iterations are considered: - track offset inside strobemeta_payload->payload directly as scalar value; - at each iteration make sure that remaining strobemeta_payload->payload capacity is sufficient for execution of read_{map,str}_var functions; - make sure that offset is tracked as unbound scalar between iterations, otherwise verifier won't be able infer that bpf_loop callback reaches identical states. Acked-by: Andrii Nakryiko Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20231121020701.26440-3-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/progs/strobemeta.h | 78 ++++++++++++++++---------- 1 file changed, 48 insertions(+), 30 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/bpf/progs/strobemeta.h b/tools/testing/selftests/bpf/progs/strobemeta.h index e02cfd380746..40df2cc26eaf 100644 --- a/tools/testing/selftests/bpf/progs/strobemeta.h +++ b/tools/testing/selftests/bpf/progs/strobemeta.h @@ -24,9 +24,11 @@ struct task_struct {}; #define STACK_TABLE_EPOCH_SHIFT 20 #define STROBE_MAX_STR_LEN 1 #define STROBE_MAX_CFGS 32 +#define READ_MAP_VAR_PAYLOAD_CAP \ + ((1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN) #define STROBE_MAX_PAYLOAD \ (STROBE_MAX_STRS * STROBE_MAX_STR_LEN + \ - STROBE_MAX_MAPS * (1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN) + STROBE_MAX_MAPS * READ_MAP_VAR_PAYLOAD_CAP) struct strobe_value_header { /* @@ -355,7 +357,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg, size_t idx, void *tls_base, struct strobe_value_generic *value, struct strobemeta_payload *data, - void *payload) + size_t off) { void *location; uint64_t len; @@ -366,7 +368,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg, return 0; bpf_probe_read_user(value, sizeof(struct strobe_value_generic), location); - len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN, value->ptr); + len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN, value->ptr); /* * if bpf_probe_read_user_str returns error (<0), due to casting to * unsinged int, it will become big number, so next check is @@ -378,14 +380,14 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg, return 0; data->str_lens[idx] = len; - return len; + return off + len; } -static __always_inline void *read_map_var(struct strobemeta_cfg *cfg, - size_t idx, void *tls_base, - struct strobe_value_generic *value, - struct strobemeta_payload *data, - void *payload) +static __always_inline uint64_t read_map_var(struct strobemeta_cfg *cfg, + size_t idx, void *tls_base, + struct strobe_value_generic *value, + struct strobemeta_payload *data, + size_t off) { struct strobe_map_descr* descr = &data->map_descrs[idx]; struct strobe_map_raw map; @@ -397,11 +399,11 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg, location = calc_location(&cfg->map_locs[idx], tls_base); if (!location) - return payload; + return off; bpf_probe_read_user(value, sizeof(struct strobe_value_generic), location); if (bpf_probe_read_user(&map, sizeof(struct strobe_map_raw), value->ptr)) - return payload; + return off; descr->id = map.id; descr->cnt = map.cnt; @@ -410,10 +412,10 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg, data->req_meta_valid = 1; } - len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN, map.tag); + len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN, map.tag); if (len <= STROBE_MAX_STR_LEN) { descr->tag_len = len; - payload += len; + off += len; } #ifdef NO_UNROLL @@ -426,22 +428,22 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg, break; descr->key_lens[i] = 0; - len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN, + len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN, map.entries[i].key); if (len <= STROBE_MAX_STR_LEN) { descr->key_lens[i] = len; - payload += len; + off += len; } descr->val_lens[i] = 0; - len = bpf_probe_read_user_str(payload, STROBE_MAX_STR_LEN, + len = bpf_probe_read_user_str(&data->payload[off], STROBE_MAX_STR_LEN, map.entries[i].val); if (len <= STROBE_MAX_STR_LEN) { descr->val_lens[i] = len; - payload += len; + off += len; } } - return payload; + return off; } #ifdef USE_BPF_LOOP @@ -455,14 +457,20 @@ struct read_var_ctx { struct strobemeta_payload *data; void *tls_base; struct strobemeta_cfg *cfg; - void *payload; + size_t payload_off; /* value gets mutated */ struct strobe_value_generic *value; enum read_type type; }; -static int read_var_callback(__u32 index, struct read_var_ctx *ctx) +static int read_var_callback(__u64 index, struct read_var_ctx *ctx) { + /* lose precision info for ctx->payload_off, verifier won't track + * double xor, barrier_var() is needed to force clang keep both xors. + */ + ctx->payload_off ^= index; + barrier_var(ctx->payload_off); + ctx->payload_off ^= index; switch (ctx->type) { case READ_INT_VAR: if (index >= STROBE_MAX_INTS) @@ -472,14 +480,18 @@ static int read_var_callback(__u32 index, struct read_var_ctx *ctx) case READ_MAP_VAR: if (index >= STROBE_MAX_MAPS) return 1; - ctx->payload = read_map_var(ctx->cfg, index, ctx->tls_base, - ctx->value, ctx->data, ctx->payload); + if (ctx->payload_off > sizeof(ctx->data->payload) - READ_MAP_VAR_PAYLOAD_CAP) + return 1; + ctx->payload_off = read_map_var(ctx->cfg, index, ctx->tls_base, + ctx->value, ctx->data, ctx->payload_off); break; case READ_STR_VAR: if (index >= STROBE_MAX_STRS) return 1; - ctx->payload += read_str_var(ctx->cfg, index, ctx->tls_base, - ctx->value, ctx->data, ctx->payload); + if (ctx->payload_off > sizeof(ctx->data->payload) - STROBE_MAX_STR_LEN) + return 1; + ctx->payload_off = read_str_var(ctx->cfg, index, ctx->tls_base, + ctx->value, ctx->data, ctx->payload_off); break; } return 0; @@ -501,7 +513,8 @@ static void *read_strobe_meta(struct task_struct *task, pid_t pid = bpf_get_current_pid_tgid() >> 32; struct strobe_value_generic value = {0}; struct strobemeta_cfg *cfg; - void *tls_base, *payload; + size_t payload_off; + void *tls_base; cfg = bpf_map_lookup_elem(&strobemeta_cfgs, &pid); if (!cfg) @@ -509,7 +522,7 @@ static void *read_strobe_meta(struct task_struct *task, data->int_vals_set_mask = 0; data->req_meta_valid = 0; - payload = data->payload; + payload_off = 0; /* * we don't have struct task_struct definition, it should be: * tls_base = (void *)task->thread.fsbase; @@ -522,7 +535,7 @@ static void *read_strobe_meta(struct task_struct *task, .tls_base = tls_base, .value = &value, .data = data, - .payload = payload, + .payload_off = 0, }; int err; @@ -540,6 +553,11 @@ static void *read_strobe_meta(struct task_struct *task, err = bpf_loop(STROBE_MAX_MAPS, read_var_callback, &ctx, 0); if (err != STROBE_MAX_MAPS) return NULL; + + payload_off = ctx.payload_off; + /* this should not really happen, here only to satisfy verifer */ + if (payload_off > sizeof(data->payload)) + payload_off = sizeof(data->payload); #else #ifdef NO_UNROLL #pragma clang loop unroll(disable) @@ -555,7 +573,7 @@ static void *read_strobe_meta(struct task_struct *task, #pragma unroll #endif /* NO_UNROLL */ for (int i = 0; i < STROBE_MAX_STRS; ++i) { - payload += read_str_var(cfg, i, tls_base, &value, data, payload); + payload_off = read_str_var(cfg, i, tls_base, &value, data, payload_off); } #ifdef NO_UNROLL #pragma clang loop unroll(disable) @@ -563,7 +581,7 @@ static void *read_strobe_meta(struct task_struct *task, #pragma unroll #endif /* NO_UNROLL */ for (int i = 0; i < STROBE_MAX_MAPS; ++i) { - payload = read_map_var(cfg, i, tls_base, &value, data, payload); + payload_off = read_map_var(cfg, i, tls_base, &value, data, payload_off); } #endif /* USE_BPF_LOOP */ @@ -571,7 +589,7 @@ static void *read_strobe_meta(struct task_struct *task, * return pointer right after end of payload, so it's possible to * calculate exact amount of useful data that needs to be sent */ - return payload; + return &data->payload[payload_off]; } SEC("raw_tracepoint/kfree_skb") -- cgit v1.2.3 From f40bfd1679446b22d321e64a1fa98b7d07d2be08 Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 21 Nov 2023 04:06:53 +0200 Subject: selftests/bpf: fix bpf_loop_bench for new callback verification scheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a preparatory change. A follow-up patch "bpf: verify callbacks as if they are called unknown number of times" changes logic for callbacks handling. While previously callbacks were verified as a single function call, new scheme takes into account that callbacks could be executed unknown number of times. This has dire implications for bpf_loop_bench: SEC("fentry/" SYS_PREFIX "sys_getpgid") int benchmark(void *ctx) { for (int i = 0; i < 1000; i++) { bpf_loop(nr_loops, empty_callback, NULL, 0); __sync_add_and_fetch(&hits, nr_loops); } return 0; } W/o callbacks change verifier sees it as a 1000 calls to empty_callback(). However, with callbacks change things become exponential: - i=0: state exploring empty_callback is scheduled with i=0 (a); - i=1: state exploring empty_callback is scheduled with i=1; ... - i=999: state exploring empty_callback is scheduled with i=999; - state (a) is popped from stack; - i=1: state exploring empty_callback is scheduled with i=1; ... Avoid this issue by rewriting outer loop as bpf_loop(). Unfortunately, this adds a function call to a loop at runtime, which negatively affects performance: throughput latency before: 149.919 ± 0.168 M ops/s, 6.670 ns/op after : 137.040 ± 0.187 M ops/s, 7.297 ns/op Acked-by: Andrii Nakryiko Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20231121020701.26440-4-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/progs/bpf_loop_bench.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/bpf/progs/bpf_loop_bench.c b/tools/testing/selftests/bpf/progs/bpf_loop_bench.c index 4ce76eb064c4..d461746fd3c1 100644 --- a/tools/testing/selftests/bpf/progs/bpf_loop_bench.c +++ b/tools/testing/selftests/bpf/progs/bpf_loop_bench.c @@ -15,13 +15,16 @@ static int empty_callback(__u32 index, void *data) return 0; } +static int outer_loop(__u32 index, void *data) +{ + bpf_loop(nr_loops, empty_callback, NULL, 0); + __sync_add_and_fetch(&hits, nr_loops); + return 0; +} + SEC("fentry/" SYS_PREFIX "sys_getpgid") int benchmark(void *ctx) { - for (int i = 0; i < 1000; i++) { - bpf_loop(nr_loops, empty_callback, NULL, 0); - - __sync_add_and_fetch(&hits, nr_loops); - } + bpf_loop(1000, outer_loop, NULL, 0); return 0; } -- cgit v1.2.3 From ab5cfac139ab8576fb54630d4cca23c3e690ee90 Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 21 Nov 2023 04:06:56 +0200 Subject: bpf: verify callbacks as if they are called unknown number of times Prior to this patch callbacks were handled as regular function calls, execution of callback body was modeled exactly once. This patch updates callbacks handling logic as follows: - introduces a function push_callback_call() that schedules callback body verification in env->head stack; - updates prepare_func_exit() to reschedule callback body verification upon BPF_EXIT; - as calls to bpf_*_iter_next(), calls to callback invoking functions are marked as checkpoints; - is_state_visited() is updated to stop callback based iteration when some identical parent state is found. Paths with callback function invoked zero times are now verified first, which leads to necessity to modify some selftests: - the following negative tests required adding release/unlock/drop calls to avoid previously masked unrelated error reports: - cb_refs.c:underflow_prog - exceptions_fail.c:reject_rbtree_add_throw - exceptions_fail.c:reject_with_cp_reference - the following precision tracking selftests needed change in expected log trace: - verifier_subprog_precision.c:callback_result_precise (note: r0 precision is no longer propagated inside callback and I think this is a correct behavior) - verifier_subprog_precision.c:parent_callee_saved_reg_precise_with_callback - verifier_subprog_precision.c:parent_stack_slot_precise_with_callback Reported-by: Andrew Werner Closes: https://lore.kernel.org/bpf/CA+vRuzPChFNXmouzGG+wsy=6eMcfr1mFG0F3g7rbg-sedGKW3w@mail.gmail.com/ Acked-by: Andrii Nakryiko Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20231121020701.26440-7-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov --- include/linux/bpf_verifier.h | 5 + kernel/bpf/verifier.c | 274 +++++++++++++-------- tools/testing/selftests/bpf/progs/cb_refs.c | 1 + .../testing/selftests/bpf/progs/exceptions_fail.c | 2 + .../bpf/progs/verifier_subprog_precision.c | 71 ++++-- 5 files changed, 240 insertions(+), 113 deletions(-) (limited to 'tools') diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 24213a99cc79..dd326936dd6f 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -400,6 +400,7 @@ struct bpf_verifier_state { struct bpf_idx_pair *jmp_history; u32 jmp_history_cnt; u32 dfs_depth; + u32 callback_unroll_depth; }; #define bpf_get_spilled_reg(slot, frame, mask) \ @@ -511,6 +512,10 @@ struct bpf_insn_aux_data { * this instruction, regardless of any heuristics */ bool force_checkpoint; + /* true if instruction is a call to a helper function that + * accepts callback function as a parameter. + */ + bool calls_callback; }; #define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */ diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 68ee4803d3a2..a60dfa56ebb3 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -547,13 +547,12 @@ static bool is_dynptr_ref_function(enum bpf_func_id func_id) return func_id == BPF_FUNC_dynptr_data; } -static bool is_callback_calling_kfunc(u32 btf_id); +static bool is_sync_callback_calling_kfunc(u32 btf_id); static bool is_bpf_throw_kfunc(struct bpf_insn *insn); -static bool is_callback_calling_function(enum bpf_func_id func_id) +static bool is_sync_callback_calling_function(enum bpf_func_id func_id) { return func_id == BPF_FUNC_for_each_map_elem || - func_id == BPF_FUNC_timer_set_callback || func_id == BPF_FUNC_find_vma || func_id == BPF_FUNC_loop || func_id == BPF_FUNC_user_ringbuf_drain; @@ -564,6 +563,18 @@ static bool is_async_callback_calling_function(enum bpf_func_id func_id) return func_id == BPF_FUNC_timer_set_callback; } +static bool is_callback_calling_function(enum bpf_func_id func_id) +{ + return is_sync_callback_calling_function(func_id) || + is_async_callback_calling_function(func_id); +} + +static bool is_sync_callback_calling_insn(struct bpf_insn *insn) +{ + return (bpf_helper_call(insn) && is_sync_callback_calling_function(insn->imm)) || + (bpf_pseudo_kfunc_call(insn) && is_sync_callback_calling_kfunc(insn->imm)); +} + static bool is_storage_get_function(enum bpf_func_id func_id) { return func_id == BPF_FUNC_sk_storage_get || @@ -1808,6 +1819,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state, dst_state->first_insn_idx = src->first_insn_idx; dst_state->last_insn_idx = src->last_insn_idx; dst_state->dfs_depth = src->dfs_depth; + dst_state->callback_unroll_depth = src->callback_unroll_depth; dst_state->used_as_loop_entry = src->used_as_loop_entry; for (i = 0; i <= src->curframe; i++) { dst = dst_state->frame[i]; @@ -3731,6 +3743,8 @@ static void fmt_stack_mask(char *buf, ssize_t buf_sz, u64 stack_mask) } } +static bool calls_callback(struct bpf_verifier_env *env, int insn_idx); + /* For given verifier state backtrack_insn() is called from the last insn to * the first insn. Its purpose is to compute a bitmask of registers and * stack slots that needs precision in the parent verifier state. @@ -3906,16 +3920,13 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, return -EFAULT; return 0; } - } else if ((bpf_helper_call(insn) && - is_callback_calling_function(insn->imm) && - !is_async_callback_calling_function(insn->imm)) || - (bpf_pseudo_kfunc_call(insn) && is_callback_calling_kfunc(insn->imm))) { - /* callback-calling helper or kfunc call, which means - * we are exiting from subprog, but unlike the subprog - * call handling above, we shouldn't propagate - * precision of r1-r5 (if any requested), as they are - * not actually arguments passed directly to callback - * subprogs + } else if (is_sync_callback_calling_insn(insn) && idx != subseq_idx - 1) { + /* exit from callback subprog to callback-calling helper or + * kfunc call. Use idx/subseq_idx check to discern it from + * straight line code backtracking. + * Unlike the subprog call handling above, we shouldn't + * propagate precision of r1-r5 (if any requested), as they are + * not actually arguments passed directly to callback subprogs */ if (bt_reg_mask(bt) & ~BPF_REGMASK_ARGS) { verbose(env, "BUG regs %x\n", bt_reg_mask(bt)); @@ -3950,10 +3961,18 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx, } else if (opcode == BPF_EXIT) { bool r0_precise; + /* Backtracking to a nested function call, 'idx' is a part of + * the inner frame 'subseq_idx' is a part of the outer frame. + * In case of a regular function call, instructions giving + * precision to registers R1-R5 should have been found already. + * In case of a callback, it is ok to have R1-R5 marked for + * backtracking, as these registers are set by the function + * invoking callback. + */ + if (subseq_idx >= 0 && calls_callback(env, subseq_idx)) + for (i = BPF_REG_1; i <= BPF_REG_5; i++) + bt_clear_reg(bt, i); if (bt_reg_mask(bt) & BPF_REGMASK_ARGS) { - /* if backtracing was looking for registers R1-R5 - * they should have been found already. - */ verbose(env, "BUG regs %x\n", bt_reg_mask(bt)); WARN_ONCE(1, "verifier backtracking bug"); return -EFAULT; @@ -9421,11 +9440,11 @@ err_out: return err; } -static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, - int *insn_idx, int subprog, - set_callee_state_fn set_callee_state_cb) +static int push_callback_call(struct bpf_verifier_env *env, struct bpf_insn *insn, + int insn_idx, int subprog, + set_callee_state_fn set_callee_state_cb) { - struct bpf_verifier_state *state = env->cur_state; + struct bpf_verifier_state *state = env->cur_state, *callback_state; struct bpf_func_state *caller, *callee; int err; @@ -9433,44 +9452,22 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn err = btf_check_subprog_call(env, subprog, caller->regs); if (err == -EFAULT) return err; - if (subprog_is_global(env, subprog)) { - if (err) { - verbose(env, "Caller passes invalid args into func#%d\n", - subprog); - return err; - } else { - if (env->log.level & BPF_LOG_LEVEL) - verbose(env, - "Func#%d is global and valid. Skipping.\n", - subprog); - clear_caller_saved_regs(env, caller->regs); - - /* All global functions return a 64-bit SCALAR_VALUE */ - mark_reg_unknown(env, caller->regs, BPF_REG_0); - caller->regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG; - - /* continue with next insn after call */ - return 0; - } - } /* set_callee_state is used for direct subprog calls, but we are * interested in validating only BPF helpers that can call subprogs as * callbacks */ - if (set_callee_state_cb != set_callee_state) { - env->subprog_info[subprog].is_cb = true; - if (bpf_pseudo_kfunc_call(insn) && - !is_callback_calling_kfunc(insn->imm)) { - verbose(env, "verifier bug: kfunc %s#%d not marked as callback-calling\n", - func_id_name(insn->imm), insn->imm); - return -EFAULT; - } else if (!bpf_pseudo_kfunc_call(insn) && - !is_callback_calling_function(insn->imm)) { /* helper */ - verbose(env, "verifier bug: helper %s#%d not marked as callback-calling\n", - func_id_name(insn->imm), insn->imm); - return -EFAULT; - } + env->subprog_info[subprog].is_cb = true; + if (bpf_pseudo_kfunc_call(insn) && + !is_sync_callback_calling_kfunc(insn->imm)) { + verbose(env, "verifier bug: kfunc %s#%d not marked as callback-calling\n", + func_id_name(insn->imm), insn->imm); + return -EFAULT; + } else if (!bpf_pseudo_kfunc_call(insn) && + !is_callback_calling_function(insn->imm)) { /* helper */ + verbose(env, "verifier bug: helper %s#%d not marked as callback-calling\n", + func_id_name(insn->imm), insn->imm); + return -EFAULT; } if (insn->code == (BPF_JMP | BPF_CALL) && @@ -9481,25 +9478,76 @@ static int __check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn /* there is no real recursion here. timer callbacks are async */ env->subprog_info[subprog].is_async_cb = true; async_cb = push_async_cb(env, env->subprog_info[subprog].start, - *insn_idx, subprog); + insn_idx, subprog); if (!async_cb) return -EFAULT; callee = async_cb->frame[0]; callee->async_entry_cnt = caller->async_entry_cnt + 1; /* Convert bpf_timer_set_callback() args into timer callback args */ - err = set_callee_state_cb(env, caller, callee, *insn_idx); + err = set_callee_state_cb(env, caller, callee, insn_idx); if (err) return err; + return 0; + } + + /* for callback functions enqueue entry to callback and + * proceed with next instruction within current frame. + */ + callback_state = push_stack(env, env->subprog_info[subprog].start, insn_idx, false); + if (!callback_state) + return -ENOMEM; + + err = setup_func_entry(env, subprog, insn_idx, set_callee_state_cb, + callback_state); + if (err) + return err; + + callback_state->callback_unroll_depth++; + return 0; +} + +static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, + int *insn_idx) +{ + struct bpf_verifier_state *state = env->cur_state; + struct bpf_func_state *caller; + int err, subprog, target_insn; + + target_insn = *insn_idx + insn->imm + 1; + subprog = find_subprog(env, target_insn); + if (subprog < 0) { + verbose(env, "verifier bug. No program starts at insn %d\n", target_insn); + return -EFAULT; + } + + caller = state->frame[state->curframe]; + err = btf_check_subprog_call(env, subprog, caller->regs); + if (err == -EFAULT) + return err; + if (subprog_is_global(env, subprog)) { + if (err) { + verbose(env, "Caller passes invalid args into func#%d\n", subprog); + return err; + } + + if (env->log.level & BPF_LOG_LEVEL) + verbose(env, "Func#%d is global and valid. Skipping.\n", subprog); clear_caller_saved_regs(env, caller->regs); + + /* All global functions return a 64-bit SCALAR_VALUE */ mark_reg_unknown(env, caller->regs, BPF_REG_0); caller->regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG; + /* continue with next insn after call */ return 0; } - err = setup_func_entry(env, subprog, *insn_idx, set_callee_state_cb, state); + /* for regular function entry setup new frame and continue + * from that frame. + */ + err = setup_func_entry(env, subprog, *insn_idx, set_callee_state, state); if (err) return err; @@ -9559,22 +9607,6 @@ static int set_callee_state(struct bpf_verifier_env *env, return 0; } -static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn, - int *insn_idx) -{ - int subprog, target_insn; - - target_insn = *insn_idx + insn->imm + 1; - subprog = find_subprog(env, target_insn); - if (subprog < 0) { - verbose(env, "verifier bug. No program starts at insn %d\n", - target_insn); - return -EFAULT; - } - - return __check_func_call(env, insn, insn_idx, subprog, set_callee_state); -} - static int set_map_elem_callback_state(struct bpf_verifier_env *env, struct bpf_func_state *caller, struct bpf_func_state *callee, @@ -9798,6 +9830,11 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) verbose_invalid_scalar(env, r0, &range, "callback return", "R0"); return -EINVAL; } + if (!calls_callback(env, callee->callsite)) { + verbose(env, "BUG: in callback at %d, callsite %d !calls_callback\n", + *insn_idx, callee->callsite); + return -EFAULT; + } } else { /* return to the caller whatever r0 had in the callee */ caller->regs[BPF_REG_0] = *r0; @@ -9815,7 +9852,15 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) return err; } - *insn_idx = callee->callsite + 1; + /* for callbacks like bpf_loop or bpf_for_each_map_elem go back to callsite, + * there function call logic would reschedule callback visit. If iteration + * converges is_state_visited() would prune that visit eventually. + */ + if (callee->in_callback_fn) + *insn_idx = callee->callsite; + else + *insn_idx = callee->callsite + 1; + if (env->log.level & BPF_LOG_LEVEL) { verbose(env, "returning from callee:\n"); print_verifier_state(env, callee, true); @@ -10228,24 +10273,24 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn } break; case BPF_FUNC_for_each_map_elem: - err = __check_func_call(env, insn, insn_idx_p, meta.subprogno, - set_map_elem_callback_state); + err = push_callback_call(env, insn, insn_idx, meta.subprogno, + set_map_elem_callback_state); break; case BPF_FUNC_timer_set_callback: - err = __check_func_call(env, insn, insn_idx_p, meta.subprogno, - set_timer_callback_state); + err = push_callback_call(env, insn, insn_idx, meta.subprogno, + set_timer_callback_state); break; case BPF_FUNC_find_vma: - err = __check_func_call(env, insn, insn_idx_p, meta.subprogno, - set_find_vma_callback_state); + err = push_callback_call(env, insn, insn_idx, meta.subprogno, + set_find_vma_callback_state); break; case BPF_FUNC_snprintf: err = check_bpf_snprintf_call(env, regs); break; case BPF_FUNC_loop: update_loop_inline_state(env, meta.subprogno); - err = __check_func_call(env, insn, insn_idx_p, meta.subprogno, - set_loop_callback_state); + err = push_callback_call(env, insn, insn_idx, meta.subprogno, + set_loop_callback_state); break; case BPF_FUNC_dynptr_from_mem: if (regs[BPF_REG_1].type != PTR_TO_MAP_VALUE) { @@ -10341,8 +10386,8 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn break; } case BPF_FUNC_user_ringbuf_drain: - err = __check_func_call(env, insn, insn_idx_p, meta.subprogno, - set_user_ringbuf_callback_state); + err = push_callback_call(env, insn, insn_idx, meta.subprogno, + set_user_ringbuf_callback_state); break; } @@ -11230,7 +11275,7 @@ static bool is_bpf_graph_api_kfunc(u32 btf_id) btf_id == special_kfunc_list[KF_bpf_refcount_acquire_impl]; } -static bool is_callback_calling_kfunc(u32 btf_id) +static bool is_sync_callback_calling_kfunc(u32 btf_id) { return btf_id == special_kfunc_list[KF_bpf_rbtree_add_impl]; } @@ -11982,6 +12027,21 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, return -EACCES; } + /* Check the arguments */ + err = check_kfunc_args(env, &meta, insn_idx); + if (err < 0) + return err; + + if (meta.func_id == special_kfunc_list[KF_bpf_rbtree_add_impl]) { + err = push_callback_call(env, insn, insn_idx, meta.subprogno, + set_rbtree_add_callback_state); + if (err) { + verbose(env, "kfunc %s#%d failed callback verification\n", + func_name, meta.func_id); + return err; + } + } + rcu_lock = is_kfunc_bpf_rcu_read_lock(&meta); rcu_unlock = is_kfunc_bpf_rcu_read_unlock(&meta); @@ -12017,10 +12077,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, return -EINVAL; } - /* Check the arguments */ - err = check_kfunc_args(env, &meta, insn_idx); - if (err < 0) - return err; /* In case of release function, we get register number of refcounted * PTR_TO_BTF_ID in bpf_kfunc_arg_meta, do the release now. */ @@ -12054,16 +12110,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn, } } - if (meta.func_id == special_kfunc_list[KF_bpf_rbtree_add_impl]) { - err = __check_func_call(env, insn, insn_idx_p, meta.subprogno, - set_rbtree_add_callback_state); - if (err) { - verbose(env, "kfunc %s#%d failed callback verification\n", - func_name, meta.func_id); - return err; - } - } - if (meta.func_id == special_kfunc_list[KF_bpf_throw]) { if (!bpf_jit_supports_exceptions()) { verbose(env, "JIT does not support calling kfunc %s#%d\n", @@ -15427,6 +15473,15 @@ static bool is_force_checkpoint(struct bpf_verifier_env *env, int insn_idx) return env->insn_aux_data[insn_idx].force_checkpoint; } +static void mark_calls_callback(struct bpf_verifier_env *env, int idx) +{ + env->insn_aux_data[idx].calls_callback = true; +} + +static bool calls_callback(struct bpf_verifier_env *env, int insn_idx) +{ + return env->insn_aux_data[insn_idx].calls_callback; +} enum { DONE_EXPLORING = 0, @@ -15540,6 +15595,21 @@ static int visit_insn(int t, struct bpf_verifier_env *env) * async state will be pushed for further exploration. */ mark_prune_point(env, t); + /* For functions that invoke callbacks it is not known how many times + * callback would be called. Verifier models callback calling functions + * by repeatedly visiting callback bodies and returning to origin call + * instruction. + * In order to stop such iteration verifier needs to identify when a + * state identical some state from a previous iteration is reached. + * Check below forces creation of checkpoint before callback calling + * instruction to allow search for such identical states. + */ + if (is_sync_callback_calling_insn(insn)) { + mark_calls_callback(env, t); + mark_force_checkpoint(env, t); + mark_prune_point(env, t); + mark_jmp_point(env, t); + } if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) { struct bpf_kfunc_call_arg_meta meta; @@ -17009,10 +17079,16 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx) } goto skip_inf_loop_check; } + if (calls_callback(env, insn_idx)) { + if (states_equal(env, &sl->state, cur, true)) + goto hit; + goto skip_inf_loop_check; + } /* attempt to detect infinite loop to avoid unnecessary doomed work */ if (states_maybe_looping(&sl->state, cur) && states_equal(env, &sl->state, cur, false) && - !iter_active_depths_differ(&sl->state, cur)) { + !iter_active_depths_differ(&sl->state, cur) && + sl->state.callback_unroll_depth == cur->callback_unroll_depth) { verbose_linfo(env, insn_idx, "; "); verbose(env, "infinite loop detected at insn %d\n", insn_idx); verbose(env, "cur state:"); diff --git a/tools/testing/selftests/bpf/progs/cb_refs.c b/tools/testing/selftests/bpf/progs/cb_refs.c index 76d661b20e87..56c764df8196 100644 --- a/tools/testing/selftests/bpf/progs/cb_refs.c +++ b/tools/testing/selftests/bpf/progs/cb_refs.c @@ -33,6 +33,7 @@ int underflow_prog(void *ctx) if (!p) return 0; bpf_for_each_map_elem(&array_map, cb1, &p, 0); + bpf_kfunc_call_test_release(p); return 0; } diff --git a/tools/testing/selftests/bpf/progs/exceptions_fail.c b/tools/testing/selftests/bpf/progs/exceptions_fail.c index 4c39e920dac2..8c0ef2742208 100644 --- a/tools/testing/selftests/bpf/progs/exceptions_fail.c +++ b/tools/testing/selftests/bpf/progs/exceptions_fail.c @@ -171,6 +171,7 @@ int reject_with_rbtree_add_throw(void *ctx) return 0; bpf_spin_lock(&lock); bpf_rbtree_add(&rbtree, &f->node, rbless); + bpf_spin_unlock(&lock); return 0; } @@ -214,6 +215,7 @@ int reject_with_cb_reference(void *ctx) if (!f) return 0; bpf_loop(5, subprog_cb_ref, NULL, 0); + bpf_obj_drop(f); return 0; } diff --git a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c index db6b3143338b..da803cffb5ef 100644 --- a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c +++ b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c @@ -119,15 +119,26 @@ __naked int global_subprog_result_precise(void) SEC("?raw_tp") __success __log_level(2) +/* First simulated path does not include callback body */ __msg("14: (0f) r1 += r6") -__msg("mark_precise: frame0: last_idx 14 first_idx 10") +__msg("mark_precise: frame0: last_idx 14 first_idx 9") __msg("mark_precise: frame0: regs=r6 stack= before 13: (bf) r1 = r7") __msg("mark_precise: frame0: regs=r6 stack= before 12: (27) r6 *= 4") __msg("mark_precise: frame0: regs=r6 stack= before 11: (25) if r6 > 0x3 goto pc+4") __msg("mark_precise: frame0: regs=r6 stack= before 10: (bf) r6 = r0") -__msg("mark_precise: frame0: parent state regs=r0 stack=:") -__msg("mark_precise: frame0: last_idx 18 first_idx 0") -__msg("mark_precise: frame0: regs=r0 stack= before 18: (95) exit") +__msg("mark_precise: frame0: regs=r0 stack= before 9: (85) call bpf_loop") +/* State entering callback body popped from states stack */ +__msg("from 9 to 17: frame1:") +__msg("17: frame1: R1=scalar() R2=0 R10=fp0 cb") +__msg("17: (b7) r0 = 0") +__msg("18: (95) exit") +__msg("returning from callee:") +__msg("to caller at 9:") +/* r4 (flags) is always precise for bpf_loop() */ +__msg("frame 0: propagating r4") +__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1") +__msg("mark_precise: frame0: regs=r4 stack= before 18: (95) exit") +__msg("from 18 to 9: safe") __naked int callback_result_precise(void) { asm volatile ( @@ -233,20 +244,36 @@ __naked int parent_callee_saved_reg_precise_global(void) SEC("?raw_tp") __success __log_level(2) +/* First simulated path does not include callback body */ __msg("12: (0f) r1 += r6") -__msg("mark_precise: frame0: last_idx 12 first_idx 10") +__msg("mark_precise: frame0: last_idx 12 first_idx 9") __msg("mark_precise: frame0: regs=r6 stack= before 11: (bf) r1 = r7") __msg("mark_precise: frame0: regs=r6 stack= before 10: (27) r6 *= 4") +__msg("mark_precise: frame0: regs=r6 stack= before 9: (85) call bpf_loop") __msg("mark_precise: frame0: parent state regs=r6 stack=:") -__msg("mark_precise: frame0: last_idx 16 first_idx 0") -__msg("mark_precise: frame0: regs=r6 stack= before 16: (95) exit") -__msg("mark_precise: frame1: regs= stack= before 15: (b7) r0 = 0") -__msg("mark_precise: frame1: regs= stack= before 9: (85) call bpf_loop#181") +__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9") __msg("mark_precise: frame0: regs=r6 stack= before 8: (b7) r4 = 0") __msg("mark_precise: frame0: regs=r6 stack= before 7: (b7) r3 = 0") __msg("mark_precise: frame0: regs=r6 stack= before 6: (bf) r2 = r8") __msg("mark_precise: frame0: regs=r6 stack= before 5: (b7) r1 = 1") __msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3") +/* State entering callback body popped from states stack */ +__msg("from 9 to 15: frame1:") +__msg("15: frame1: R1=scalar() R2=0 R10=fp0 cb") +__msg("15: (b7) r0 = 0") +__msg("16: (95) exit") +__msg("returning from callee:") +__msg("to caller at 9:") +/* r4 (flags) is always precise for bpf_loop(), + * r6 was marked before backtracking to callback body. + */ +__msg("frame 0: propagating r4,r6") +__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1") +__msg("mark_precise: frame0: regs=r4,r6 stack= before 16: (95) exit") +__msg("mark_precise: frame1: regs= stack= before 15: (b7) r0 = 0") +__msg("mark_precise: frame1: regs= stack= before 9: (85) call bpf_loop") +__msg("mark_precise: frame0: parent state regs= stack=:") +__msg("from 16 to 9: safe") __naked int parent_callee_saved_reg_precise_with_callback(void) { asm volatile ( @@ -373,22 +400,38 @@ __naked int parent_stack_slot_precise_global(void) SEC("?raw_tp") __success __log_level(2) +/* First simulated path does not include callback body */ __msg("14: (0f) r1 += r6") -__msg("mark_precise: frame0: last_idx 14 first_idx 11") +__msg("mark_precise: frame0: last_idx 14 first_idx 10") __msg("mark_precise: frame0: regs=r6 stack= before 13: (bf) r1 = r7") __msg("mark_precise: frame0: regs=r6 stack= before 12: (27) r6 *= 4") __msg("mark_precise: frame0: regs=r6 stack= before 11: (79) r6 = *(u64 *)(r10 -8)") +__msg("mark_precise: frame0: regs= stack=-8 before 10: (85) call bpf_loop") __msg("mark_precise: frame0: parent state regs= stack=-8:") -__msg("mark_precise: frame0: last_idx 18 first_idx 0") -__msg("mark_precise: frame0: regs= stack=-8 before 18: (95) exit") -__msg("mark_precise: frame1: regs= stack= before 17: (b7) r0 = 0") -__msg("mark_precise: frame1: regs= stack= before 10: (85) call bpf_loop#181") +__msg("mark_precise: frame0: last_idx 9 first_idx 0 subseq_idx 10") __msg("mark_precise: frame0: regs= stack=-8 before 9: (b7) r4 = 0") __msg("mark_precise: frame0: regs= stack=-8 before 8: (b7) r3 = 0") __msg("mark_precise: frame0: regs= stack=-8 before 7: (bf) r2 = r8") __msg("mark_precise: frame0: regs= stack=-8 before 6: (bf) r1 = r6") __msg("mark_precise: frame0: regs= stack=-8 before 5: (7b) *(u64 *)(r10 -8) = r6") __msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3") +/* State entering callback body popped from states stack */ +__msg("from 10 to 17: frame1:") +__msg("17: frame1: R1=scalar() R2=0 R10=fp0 cb") +__msg("17: (b7) r0 = 0") +__msg("18: (95) exit") +__msg("returning from callee:") +__msg("to caller at 10:") +/* r4 (flags) is always precise for bpf_loop(), + * fp-8 was marked before backtracking to callback body. + */ +__msg("frame 0: propagating r4,fp-8") +__msg("mark_precise: frame0: last_idx 10 first_idx 10 subseq_idx -1") +__msg("mark_precise: frame0: regs=r4 stack=-8 before 18: (95) exit") +__msg("mark_precise: frame1: regs= stack= before 17: (b7) r0 = 0") +__msg("mark_precise: frame1: regs= stack= before 10: (85) call bpf_loop#181") +__msg("mark_precise: frame0: parent state regs= stack=:") +__msg("from 18 to 10: safe") __naked int parent_stack_slot_precise_with_callback(void) { asm volatile ( -- cgit v1.2.3 From 958465e217dbf5fc6677d42d8827fb3073d86afd Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 21 Nov 2023 04:06:57 +0200 Subject: selftests/bpf: tests for iterating callbacks A set of test cases to check behavior of callback handling logic, check if verifier catches the following situations: - program not safe on second callback iteration; - program not safe on zero callback iterations; - infinite loop inside a callback. Verify that callback logic works for bpf_loop, bpf_for_each_map_elem, bpf_user_ringbuf_drain, bpf_find_vma. Acked-by: Andrii Nakryiko Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20231121020701.26440-8-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/prog_tests/verifier.c | 2 + .../bpf/progs/verifier_iterating_callbacks.c | 147 +++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c (limited to 'tools') diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c index e5c61aa6604a..5cfa7a6316b6 100644 --- a/tools/testing/selftests/bpf/prog_tests/verifier.c +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c @@ -31,6 +31,7 @@ #include "verifier_helper_restricted.skel.h" #include "verifier_helper_value_access.skel.h" #include "verifier_int_ptr.skel.h" +#include "verifier_iterating_callbacks.skel.h" #include "verifier_jeq_infer_not_null.skel.h" #include "verifier_ld_ind.skel.h" #include "verifier_ldsx.skel.h" @@ -139,6 +140,7 @@ void test_verifier_helper_packet_access(void) { RUN(verifier_helper_packet_acces void test_verifier_helper_restricted(void) { RUN(verifier_helper_restricted); } void test_verifier_helper_value_access(void) { RUN(verifier_helper_value_access); } void test_verifier_int_ptr(void) { RUN(verifier_int_ptr); } +void test_verifier_iterating_callbacks(void) { RUN(verifier_iterating_callbacks); } void test_verifier_jeq_infer_not_null(void) { RUN(verifier_jeq_infer_not_null); } void test_verifier_ld_ind(void) { RUN(verifier_ld_ind); } void test_verifier_ldsx(void) { RUN(verifier_ldsx); } diff --git a/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c new file mode 100644 index 000000000000..fa9429f77a81 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include "bpf_misc.h" + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 8); + __type(key, __u32); + __type(value, __u64); +} map SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_USER_RINGBUF); + __uint(max_entries, 8); +} ringbuf SEC(".maps"); + +struct vm_area_struct; +struct bpf_map; + +struct buf_context { + char *buf; +}; + +struct num_context { + __u64 i; +}; + +__u8 choice_arr[2] = { 0, 1 }; + +static int unsafe_on_2nd_iter_cb(__u32 idx, struct buf_context *ctx) +{ + if (idx == 0) { + ctx->buf = (char *)(0xDEAD); + return 0; + } + + if (bpf_probe_read_user(ctx->buf, 8, (void *)(0xBADC0FFEE))) + return 1; + + return 0; +} + +SEC("?raw_tp") +__failure __msg("R1 type=scalar expected=fp") +int unsafe_on_2nd_iter(void *unused) +{ + char buf[4]; + struct buf_context loop_ctx = { .buf = buf }; + + bpf_loop(100, unsafe_on_2nd_iter_cb, &loop_ctx, 0); + return 0; +} + +static int unsafe_on_zero_iter_cb(__u32 idx, struct num_context *ctx) +{ + ctx->i = 0; + return 0; +} + +SEC("?raw_tp") +__failure __msg("invalid access to map value, value_size=2 off=32 size=1") +int unsafe_on_zero_iter(void *unused) +{ + struct num_context loop_ctx = { .i = 32 }; + + bpf_loop(100, unsafe_on_zero_iter_cb, &loop_ctx, 0); + return choice_arr[loop_ctx.i]; +} + +static int loop_detection_cb(__u32 idx, struct num_context *ctx) +{ + for (;;) {} + return 0; +} + +SEC("?raw_tp") +__failure __msg("infinite loop detected") +int loop_detection(void *unused) +{ + struct num_context loop_ctx = { .i = 0 }; + + bpf_loop(100, loop_detection_cb, &loop_ctx, 0); + return 0; +} + +static __always_inline __u64 oob_state_machine(struct num_context *ctx) +{ + switch (ctx->i) { + case 0: + ctx->i = 1; + break; + case 1: + ctx->i = 32; + break; + } + return 0; +} + +static __u64 for_each_map_elem_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data) +{ + return oob_state_machine(data); +} + +SEC("?raw_tp") +__failure __msg("invalid access to map value, value_size=2 off=32 size=1") +int unsafe_for_each_map_elem(void *unused) +{ + struct num_context loop_ctx = { .i = 0 }; + + bpf_for_each_map_elem(&map, for_each_map_elem_cb, &loop_ctx, 0); + return choice_arr[loop_ctx.i]; +} + +static __u64 ringbuf_drain_cb(struct bpf_dynptr *dynptr, void *data) +{ + return oob_state_machine(data); +} + +SEC("?raw_tp") +__failure __msg("invalid access to map value, value_size=2 off=32 size=1") +int unsafe_ringbuf_drain(void *unused) +{ + struct num_context loop_ctx = { .i = 0 }; + + bpf_user_ringbuf_drain(&ringbuf, ringbuf_drain_cb, &loop_ctx, 0); + return choice_arr[loop_ctx.i]; +} + +static __u64 find_vma_cb(struct task_struct *task, struct vm_area_struct *vma, void *data) +{ + return oob_state_machine(data); +} + +SEC("?raw_tp") +__failure __msg("invalid access to map value, value_size=2 off=32 size=1") +int unsafe_find_vma(void *unused) +{ + struct task_struct *task = bpf_get_current_task_btf(); + struct num_context loop_ctx = { .i = 0 }; + + bpf_find_vma(task, 0, find_vma_cb, &loop_ctx, 0); + return choice_arr[loop_ctx.i]; +} + +char _license[] SEC("license") = "GPL"; -- cgit v1.2.3 From 9f3330aa644d6d979eb064c46e85c62d4b4eac75 Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 21 Nov 2023 04:06:59 +0200 Subject: selftests/bpf: test widening for iterating callbacks A test case to verify that imprecise scalars widening is applied to callback entering state, when callback call is simulated repeatedly. Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20231121020701.26440-10-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov --- .../bpf/progs/verifier_iterating_callbacks.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c index fa9429f77a81..598c1e984b26 100644 --- a/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c +++ b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c @@ -25,6 +25,7 @@ struct buf_context { struct num_context { __u64 i; + __u64 j; }; __u8 choice_arr[2] = { 0, 1 }; @@ -69,6 +70,25 @@ int unsafe_on_zero_iter(void *unused) return choice_arr[loop_ctx.i]; } +static int widening_cb(__u32 idx, struct num_context *ctx) +{ + ++ctx->i; + return 0; +} + +SEC("?raw_tp") +__success +int widening(void *unused) +{ + struct num_context loop_ctx = { .i = 0, .j = 1 }; + + bpf_loop(100, widening_cb, &loop_ctx, 0); + /* loop_ctx.j is not changed during callback iteration, + * verifier should not apply widening to it. + */ + return choice_arr[loop_ctx.j]; +} + static int loop_detection_cb(__u32 idx, struct num_context *ctx) { for (;;) {} -- cgit v1.2.3 From bb124da69c47dd98d69361ec13244ece50bec63e Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 21 Nov 2023 04:07:00 +0200 Subject: bpf: keep track of max number of bpf_loop callback iterations In some cases verifier can't infer convergence of the bpf_loop() iteration. E.g. for the following program: static int cb(__u32 idx, struct num_context* ctx) { ctx->i++; return 0; } SEC("?raw_tp") int prog(void *_) { struct num_context ctx = { .i = 0 }; __u8 choice_arr[2] = { 0, 1 }; bpf_loop(2, cb, &ctx, 0); return choice_arr[ctx.i]; } Each 'cb' simulation would eventually return to 'prog' and reach 'return choice_arr[ctx.i]' statement. At which point ctx.i would be marked precise, thus forcing verifier to track multitude of separate states with {.i=0}, {.i=1}, ... at bpf_loop() callback entry. This commit allows "brute force" handling for such cases by limiting number of callback body simulations using 'umax' value of the first bpf_loop() parameter. For this, extend bpf_func_state with 'callback_depth' field. Increment this field when callback visiting state is pushed to states traversal stack. For frame #N it's 'callback_depth' field counts how many times callback with frame depth N+1 had been executed. Use bpf_func_state specifically to allow independent tracking of callback depths when multiple nested bpf_loop() calls are present. Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20231121020701.26440-11-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov --- include/linux/bpf_verifier.h | 11 +++++++ kernel/bpf/verifier.c | 19 ++++++++++-- .../bpf/progs/verifier_subprog_precision.c | 35 +++++++++++++++------- 3 files changed, 53 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index dd326936dd6f..aa4d19d0bc94 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -301,6 +301,17 @@ struct bpf_func_state { struct tnum callback_ret_range; bool in_async_callback_fn; bool in_exception_callback_fn; + /* For callback calling functions that limit number of possible + * callback executions (e.g. bpf_loop) keeps track of current + * simulated iteration number. + * Value in frame N refers to number of times callback with frame + * N+1 was simulated, e.g. for the following call: + * + * bpf_loop(..., fn, ...); | suppose current frame is N + * | fn would be simulated in frame N+1 + * | number of simulations is tracked in frame N + */ + u32 callback_depth; /* The following fields should be last. See copy_func_state() */ int acquired_refs; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 2f03e6b11bb9..af2819d5c8ee 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -9505,6 +9505,8 @@ static int push_callback_call(struct bpf_verifier_env *env, struct bpf_insn *ins return err; callback_state->callback_unroll_depth++; + callback_state->frame[callback_state->curframe - 1]->callback_depth++; + caller->callback_depth = 0; return 0; } @@ -10309,8 +10311,21 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn break; case BPF_FUNC_loop: update_loop_inline_state(env, meta.subprogno); - err = push_callback_call(env, insn, insn_idx, meta.subprogno, - set_loop_callback_state); + /* Verifier relies on R1 value to determine if bpf_loop() iteration + * is finished, thus mark it precise. + */ + err = mark_chain_precision(env, BPF_REG_1); + if (err) + return err; + if (cur_func(env)->callback_depth < regs[BPF_REG_1].umax_value) { + err = push_callback_call(env, insn, insn_idx, meta.subprogno, + set_loop_callback_state); + } else { + cur_func(env)->callback_depth = 0; + if (env->log.level & BPF_LOG_LEVEL2) + verbose(env, "frame%d bpf_loop iteration limit reached\n", + env->cur_state->curframe); + } break; case BPF_FUNC_dynptr_from_mem: if (regs[BPF_REG_1].type != PTR_TO_MAP_VALUE) { diff --git a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c index da803cffb5ef..f61d623b1ce8 100644 --- a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c +++ b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c @@ -119,7 +119,23 @@ __naked int global_subprog_result_precise(void) SEC("?raw_tp") __success __log_level(2) -/* First simulated path does not include callback body */ +/* First simulated path does not include callback body, + * r1 and r4 are always precise for bpf_loop() calls. + */ +__msg("9: (85) call bpf_loop#181") +__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1") +__msg("mark_precise: frame0: parent state regs=r4 stack=:") +__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9") +__msg("mark_precise: frame0: regs=r4 stack= before 8: (b7) r4 = 0") +__msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1") +__msg("mark_precise: frame0: parent state regs=r1 stack=:") +__msg("mark_precise: frame0: last_idx 8 first_idx 0 subseq_idx 9") +__msg("mark_precise: frame0: regs=r1 stack= before 8: (b7) r4 = 0") +__msg("mark_precise: frame0: regs=r1 stack= before 7: (b7) r3 = 0") +__msg("mark_precise: frame0: regs=r1 stack= before 6: (bf) r2 = r8") +__msg("mark_precise: frame0: regs=r1 stack= before 5: (bf) r1 = r6") +__msg("mark_precise: frame0: regs=r6 stack= before 4: (b7) r6 = 3") +/* r6 precision propagation */ __msg("14: (0f) r1 += r6") __msg("mark_precise: frame0: last_idx 14 first_idx 9") __msg("mark_precise: frame0: regs=r6 stack= before 13: (bf) r1 = r7") @@ -134,10 +150,9 @@ __msg("17: (b7) r0 = 0") __msg("18: (95) exit") __msg("returning from callee:") __msg("to caller at 9:") -/* r4 (flags) is always precise for bpf_loop() */ -__msg("frame 0: propagating r4") +__msg("frame 0: propagating r1,r4") __msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1") -__msg("mark_precise: frame0: regs=r4 stack= before 18: (95) exit") +__msg("mark_precise: frame0: regs=r1,r4 stack= before 18: (95) exit") __msg("from 18 to 9: safe") __naked int callback_result_precise(void) { @@ -264,12 +279,12 @@ __msg("15: (b7) r0 = 0") __msg("16: (95) exit") __msg("returning from callee:") __msg("to caller at 9:") -/* r4 (flags) is always precise for bpf_loop(), +/* r1, r4 are always precise for bpf_loop(), * r6 was marked before backtracking to callback body. */ -__msg("frame 0: propagating r4,r6") +__msg("frame 0: propagating r1,r4,r6") __msg("mark_precise: frame0: last_idx 9 first_idx 9 subseq_idx -1") -__msg("mark_precise: frame0: regs=r4,r6 stack= before 16: (95) exit") +__msg("mark_precise: frame0: regs=r1,r4,r6 stack= before 16: (95) exit") __msg("mark_precise: frame1: regs= stack= before 15: (b7) r0 = 0") __msg("mark_precise: frame1: regs= stack= before 9: (85) call bpf_loop") __msg("mark_precise: frame0: parent state regs= stack=:") @@ -422,12 +437,12 @@ __msg("17: (b7) r0 = 0") __msg("18: (95) exit") __msg("returning from callee:") __msg("to caller at 10:") -/* r4 (flags) is always precise for bpf_loop(), +/* r1, r4 are always precise for bpf_loop(), * fp-8 was marked before backtracking to callback body. */ -__msg("frame 0: propagating r4,fp-8") +__msg("frame 0: propagating r1,r4,fp-8") __msg("mark_precise: frame0: last_idx 10 first_idx 10 subseq_idx -1") -__msg("mark_precise: frame0: regs=r4 stack=-8 before 18: (95) exit") +__msg("mark_precise: frame0: regs=r1,r4 stack=-8 before 18: (95) exit") __msg("mark_precise: frame1: regs= stack= before 17: (b7) r0 = 0") __msg("mark_precise: frame1: regs= stack= before 10: (85) call bpf_loop#181") __msg("mark_precise: frame0: parent state regs= stack=:") -- cgit v1.2.3 From 57e2a52deeb12ab84c15c6d0fb93638b5b94001b Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 21 Nov 2023 04:07:01 +0200 Subject: selftests/bpf: check if max number of bpf_loop iterations is tracked Check that even if bpf_loop() callback simulation does not converge to a specific state, verification could proceed via "brute force" simulation of maximal number of callback calls. Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20231121020701.26440-12-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov --- .../bpf/progs/verifier_iterating_callbacks.c | 75 ++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'tools') diff --git a/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c index 598c1e984b26..5905e036e0ea 100644 --- a/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c +++ b/tools/testing/selftests/bpf/progs/verifier_iterating_callbacks.c @@ -164,4 +164,79 @@ int unsafe_find_vma(void *unused) return choice_arr[loop_ctx.i]; } +static int iter_limit_cb(__u32 idx, struct num_context *ctx) +{ + ctx->i++; + return 0; +} + +SEC("?raw_tp") +__success +int bpf_loop_iter_limit_ok(void *unused) +{ + struct num_context ctx = { .i = 0 }; + + bpf_loop(1, iter_limit_cb, &ctx, 0); + return choice_arr[ctx.i]; +} + +SEC("?raw_tp") +__failure __msg("invalid access to map value, value_size=2 off=2 size=1") +int bpf_loop_iter_limit_overflow(void *unused) +{ + struct num_context ctx = { .i = 0 }; + + bpf_loop(2, iter_limit_cb, &ctx, 0); + return choice_arr[ctx.i]; +} + +static int iter_limit_level2a_cb(__u32 idx, struct num_context *ctx) +{ + ctx->i += 100; + return 0; +} + +static int iter_limit_level2b_cb(__u32 idx, struct num_context *ctx) +{ + ctx->i += 10; + return 0; +} + +static int iter_limit_level1_cb(__u32 idx, struct num_context *ctx) +{ + ctx->i += 1; + bpf_loop(1, iter_limit_level2a_cb, ctx, 0); + bpf_loop(1, iter_limit_level2b_cb, ctx, 0); + return 0; +} + +/* Check that path visiting every callback function once had been + * reached by verifier. Variables 'ctx{1,2}i' below serve as flags, + * with each decimal digit corresponding to a callback visit marker. + */ +SEC("socket") +__success __retval(111111) +int bpf_loop_iter_limit_nested(void *unused) +{ + struct num_context ctx1 = { .i = 0 }; + struct num_context ctx2 = { .i = 0 }; + __u64 a, b, c; + + bpf_loop(1, iter_limit_level1_cb, &ctx1, 0); + bpf_loop(1, iter_limit_level1_cb, &ctx2, 0); + a = ctx1.i; + b = ctx2.i; + /* Force 'ctx1.i' and 'ctx2.i' precise. */ + c = choice_arr[(a + b) % 2]; + /* This makes 'c' zero, but neither clang nor verifier know it. */ + c /= 10; + /* Make sure that verifier does not visit 'impossible' states: + * enumerate all possible callback visit masks. + */ + if (a != 0 && a != 1 && a != 11 && a != 101 && a != 111 && + b != 0 && b != 1 && b != 11 && b != 101 && b != 111) + asm volatile ("r0 /= 0;" ::: "r0"); + return 1000 * a + b + c; +} + char _license[] SEC("license") = "GPL"; -- cgit v1.2.3 From f0863888f6cfef33e3117dccfe94fa78edf76be4 Mon Sep 17 00:00:00 2001 From: Arseniy Krasnov Date: Wed, 22 Nov 2023 00:16:42 +0300 Subject: vsock/test: fix SEQPACKET message bounds test Tune message length calculation to make this test work on machines where 'getpagesize()' returns >32KB. Now maximum message length is not hardcoded (on machines above it was smaller than 'getpagesize()' return value, thus we get negative value and test fails), but calculated at runtime and always bigger than 'getpagesize()' result. Reproduced on aarch64 with 64KB page size. Fixes: 5c338112e48a ("test/vsock: rework message bounds test") Signed-off-by: Arseniy Krasnov Reported-by: Bogdan Marcynkov Reviewed-by: Stefano Garzarella Link: https://lore.kernel.org/r/20231121211642.163474-1-avkrasnov@salutedevices.com Signed-off-by: Jakub Kicinski --- tools/testing/vsock/vsock_test.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c index 5b0e93f9996c..01fa816868bc 100644 --- a/tools/testing/vsock/vsock_test.c +++ b/tools/testing/vsock/vsock_test.c @@ -353,11 +353,12 @@ static void test_stream_msg_peek_server(const struct test_opts *opts) } #define SOCK_BUF_SIZE (2 * 1024 * 1024) -#define MAX_MSG_SIZE (32 * 1024) +#define MAX_MSG_PAGES 4 static void test_seqpacket_msg_bounds_client(const struct test_opts *opts) { unsigned long curr_hash; + size_t max_msg_size; int page_size; int msg_count; int fd; @@ -373,7 +374,8 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts) curr_hash = 0; page_size = getpagesize(); - msg_count = SOCK_BUF_SIZE / MAX_MSG_SIZE; + max_msg_size = MAX_MSG_PAGES * page_size; + msg_count = SOCK_BUF_SIZE / max_msg_size; for (int i = 0; i < msg_count; i++) { size_t buf_size; @@ -383,7 +385,7 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts) /* Use "small" buffers and "big" buffers. */ if (i & 1) buf_size = page_size + - (rand() % (MAX_MSG_SIZE - page_size)); + (rand() % (max_msg_size - page_size)); else buf_size = 1 + (rand() % page_size); @@ -429,7 +431,6 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts) unsigned long remote_hash; unsigned long curr_hash; int fd; - char buf[MAX_MSG_SIZE]; struct msghdr msg = {0}; struct iovec iov = {0}; @@ -457,8 +458,13 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts) control_writeln("SRVREADY"); /* Wait, until peer sends whole data. */ control_expectln("SENDDONE"); - iov.iov_base = buf; - iov.iov_len = sizeof(buf); + iov.iov_len = MAX_MSG_PAGES * getpagesize(); + iov.iov_base = malloc(iov.iov_len); + if (!iov.iov_base) { + perror("malloc"); + exit(EXIT_FAILURE); + } + msg.msg_iov = &iov; msg.msg_iovlen = 1; @@ -483,6 +489,7 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts) curr_hash += hash_djb2(msg.msg_iov[0].iov_base, recv_size); } + free(iov.iov_base); close(fd); remote_hash = control_readulong(); -- cgit v1.2.3 From 2be35a619482c1f4e5bc7a2d84049b8d7d171882 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 22 Nov 2023 19:06:24 -0800 Subject: tools: ynl: fix header path for nfsd The makefile dependency is trying to include the wrong header: : fatal error: ../../../../include/uapi//linux/nfsd.h: No such file or directory The guard also looks wrong. Fixes: f14122b2c2ac ("tools: ynl: Add source files for nfsd netlink protocol") Reviewed-by: Chuck Lever Link: https://lore.kernel.org/r/20231123030624.1611925-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/Makefile.deps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps index 64d139400db1..3110f84dd029 100644 --- a/tools/net/ynl/Makefile.deps +++ b/tools/net/ynl/Makefile.deps @@ -18,4 +18,4 @@ CFLAGS_devlink:=$(call get_hdr_inc,_LINUX_DEVLINK_H_,devlink.h) CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_H_,ethtool_netlink.h) CFLAGS_handshake:=$(call get_hdr_inc,_LINUX_HANDSHAKE_H,handshake.h) CFLAGS_netdev:=$(call get_hdr_inc,_LINUX_NETDEV_H,netdev.h) -CFLAGS_nfsd:=$(call get_hdr_inc,_LINUX_NFSD_H,nfsd.h) +CFLAGS_nfsd:=$(call get_hdr_inc,_LINUX_NFSD_NETLINK_H,nfsd_netlink.h) -- cgit v1.2.3 From 39f04b1406b23fcc129a67e70d6205d5a7322f38 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 22 Nov 2023 19:05:58 -0800 Subject: tools: ynl: fix duplicate op name in devlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't support CRUD-inspired message types in YNL too well. One aspect that currently trips us up is the fact that single message ID can be used in multiple commands (as the response). This leads to duplicate entries in the id-to-string tables: devlink-user.c:19:34: warning: initialized field overwritten [-Woverride-init] 19 | [DEVLINK_CMD_PORT_NEW] = "port-new", | ^~~~~~~~~~ devlink-user.c:19:34: note: (near initialization for ‘devlink_op_strmap[7]’) Fixes tag points at where the code was generated, the "real" problem is that the code generator does not support CRUD. Fixes: f2f9dd164db0 ("netlink: specs: devlink: add the remaining command to generate complete split_ops") Link: https://lore.kernel.org/r/20231123030558.1611831-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/generated/devlink-user.c | 2 +- tools/net/ynl/ynl-gen-c.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/net/ynl/generated/devlink-user.c b/tools/net/ynl/generated/devlink-user.c index bc5065bd99b2..c12ca87ca2bb 100644 --- a/tools/net/ynl/generated/devlink-user.c +++ b/tools/net/ynl/generated/devlink-user.c @@ -15,7 +15,7 @@ /* Enums */ static const char * const devlink_op_strmap[] = { [3] = "get", - [7] = "port-get", + // skip "port-get", duplicate reply value [DEVLINK_CMD_PORT_NEW] = "port-new", [13] = "sb-get", [17] = "sb-pool-get", diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index c4003a83cd5d..3bd6b928c14f 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -1505,6 +1505,12 @@ def put_op_name(family, cw): cw.block_start(line=f"static const char * const {map_name}[] =") for op_name, op in family.msgs.items(): if op.rsp_value: + # Make sure we don't add duplicated entries, if multiple commands + # produce the same response in legacy families. + if family.rsp_by_value[op.rsp_value] != op: + cw.p(f'// skip "{op_name}", duplicate reply value') + continue + if op.req_value == op.rsp_value: cw.p(f'[{op.enum_name}] = "{op_name}",') else: -- cgit v1.2.3