:p
atchew
Login
The idea here is to expose the DTS sensors through XENPF_resource_op and expose it for the user through xenpm. v3: - use msr-index.h instead of adding defines to MSRs in xenpm v2: - moved userland part to xenpm - use cpu policy infrastructure instead of inline cpuid Teddy Astie (3): x86/cpu-policy: Infrastructure for CPUID leaf 0x6 x86/platform: Expose DTS sensors MSR xenpm: Add get-intel-temp subcommand tools/misc/xenpm.c | 91 +++++++++++++++++++++++++++- xen/arch/x86/include/asm/msr-index.h | 3 + xen/arch/x86/platform_hypercall.c | 6 ++ xen/include/xen/lib/x86/cpu-policy.h | 27 ++++++++- 4 files changed, 125 insertions(+), 2 deletions(-) -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
From: Jan Beulich <jbeulich@suse.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Teddy Astie <teddy.astie@vates.tech> --- xen/include/xen/lib/x86/cpu-policy.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/xen/include/xen/lib/x86/cpu-policy.h b/xen/include/xen/lib/x86/cpu-policy.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/xen/lib/x86/cpu-policy.h +++ b/xen/include/xen/lib/x86/cpu-policy.h @@ -XXX,XX +XXX,XX @@ struct cpu_policy uint64_t :64, :64; /* Leaf 0x3 - PSN. */ uint64_t :64, :64; /* Leaf 0x4 - Structured Cache. */ uint64_t :64, :64; /* Leaf 0x5 - MONITOR. */ - uint64_t :64, :64; /* Leaf 0x6 - Therm/Perf. */ + + /* Leaf 0x6 - Therm/Perf. */ + struct { + uint32_t /* a */ + dts:1, + turbo:1, + arat:1, + :4, + hwp:1, + hwp_notification:1, + hwp_activity_window:1, + hwp_epp:1, + hwp_plr:1, + :1, + hdc:1, + :2, + hwp_peci:1, + :2, + hw_feedback:1, + :12; + uint32_t /* b */:32; + uint32_t /* c */ aperfmperf:1, + :31; + uint32_t /* d */:32; + } pm; + uint64_t :64, :64; /* Leaf 0x7 - Structured Features. */ uint64_t :64, :64; /* Leaf 0x8 - rsvd */ uint64_t :64, :64; /* Leaf 0x9 - DCA */ -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
Intel provide CPU sensors through "DTS" MSRs. As there MSR are core-specific (or package-specific), we can't reliably fetch them from Dom0 directly. Expose these MSR (if supported) through XENPF_resource_op so that it is accessible through hypercall. Suggested-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Teddy Astie <teddy.astie@vates.tech> --- xen/arch/x86/include/asm/msr-index.h | 3 +++ xen/arch/x86/platform_hypercall.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/asm/msr-index.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/include/asm/msr-index.h +++ b/xen/arch/x86/include/asm/msr-index.h @@ -XXX,XX +XXX,XX @@ #define MCU_OPT_CTRL_GDS_MIT_DIS (_AC(1, ULL) << 4) #define MCU_OPT_CTRL_GDS_MIT_LOCK (_AC(1, ULL) << 5) +#define MSR_TEMPERATURE_TARGET 0x000001a2 +#define MSR_PACKAGE_THERM_STATUS 0x000001b1 + #define MSR_FRED_RSP_SL0 0x000001cc #define MSR_FRED_RSP_SL1 0x000001cd #define MSR_FRED_RSP_SL2 0x000001ce diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -XXX,XX +XXX,XX @@ #include <asm/current.h> #include <public/platform.h> #include <acpi/cpufreq/processor_perf.h> +#include <asm/cpu-policy.h> #include <asm/edd.h> #include <asm/microcode.h> #include <asm/mtrr.h> @@ -XXX,XX +XXX,XX @@ static bool msr_read_allowed(unsigned int msr) case MSR_MCU_OPT_CTRL: return cpu_has_srbds_ctrl; + + case MSR_IA32_THERM_STATUS: + case MSR_TEMPERATURE_TARGET: + case MSR_PACKAGE_THERM_STATUS: + return raw_cpu_policy.basic.pm.dts; } if ( ppin_msr && msr == ppin_msr ) -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
get-intel-temp allows querying the per-core CPU temperature and per-package one on Intel processors (as usual Dom0 drivers cannot work due to misalignment between Dom0 vCPU and pCPUs). Signed-off-by: Teddy Astie <teddy.astie@vates.tech> --- tools/misc/xenpm.c | 91 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c index XXXXXXX..XXXXXXX 100644 --- a/tools/misc/xenpm.c +++ b/tools/misc/xenpm.c @@ -XXX,XX +XXX,XX @@ #include <inttypes.h> #include <sys/time.h> +#include <xen/asm/msr-index.h> #include <xen-tools/common-macros.h> #define MAX_PKG_RESIDENCIES 12 @@ -XXX,XX +XXX,XX @@ static xc_interface *xc_handle; static unsigned int max_cpu_nr; +static xc_physinfo_t physinfo; /* help message */ void show_help(void) @@ -XXX,XX +XXX,XX @@ void show_help(void) " units default to \"us\" if unspecified.\n" " truncates un-representable values.\n" " 0 lets the hardware decide.\n" + " get-intel-temp [cpuid] get Intel CPU temperature of <cpuid> or all\n" " start [seconds] start collect Cx/Px statistics,\n" " output after CTRL-C or SIGINT or several seconds.\n" " enable-turbo-mode [cpuid] enable Turbo Mode for processors that support it.\n" @@ -XXX,XX +XXX,XX @@ void enable_turbo_mode(int argc, char *argv[]) errno, strerror(errno)); } +static int fetch_dts_temp(xc_interface *xch, uint32_t cpu, bool package, int *temp) +{ + xc_resource_entry_t entries[2] = { + (xc_resource_entry_t){ + .idx = package ? MSR_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS + }, + (xc_resource_entry_t){ .idx = MSR_TEMPERATURE_TARGET }, + }; + struct xc_resource_op ops = { + .cpu = cpu, + .entries = entries, + .nr_entries = 2, + }; + int tjmax; + + int ret = xc_resource_op(xch, 1, &ops); + + if ( ret <= 0 ) + /* This CPU isn't online or can't query this MSR */ + return ret ?: -EOPNOTSUPP; + + if ( ret == 2 ) + tjmax = (entries[1].val >> 16) & 0xff; + else + { + /* + * The CPU doesn't support MSR_IA32_TEMPERATURE_TARGET, we assume it's 100 which + * is correct aside a few selected Atom CPUs. Check coretemp source code for more + * information. + */ + fprintf(stderr, "[CPU%d] MSR_IA32_TEMPERATURE_TARGET is not supported, assume " + "tjmax=100°C, readings may be incorrect\n", cpu); + tjmax = 100; + } + + *temp = tjmax - ((entries[0].val >> 16) & 0xff); + return 0; +} + + +void get_intel_temp(int argc, char *argv[]) +{ + int temp, cpu = -1; + unsigned int socket; + bool has_data = false; + + if ( argc > 0 ) + parse_cpuid(argv[0], &cpu); + + if ( cpu != -1 ) + { + if ( !fetch_dts_temp(xc_handle, cpu, false, &temp) ) + printf("CPU%d: %d°C\n", cpu, temp); + else + printf("No data\n"); + return; + } + + /* Per socket measurement */ + for ( socket = 0, cpu = 0; cpu < max_cpu_nr; + socket++, cpu += physinfo.cores_per_socket * physinfo.threads_per_core ) + { + if ( !fetch_dts_temp(xc_handle, cpu, true, &temp) ) + { + has_data = true; + printf("Package%d: %d°C\n", socket, temp); + } + } + + if ( has_data ) + /* Avoid inserting a trailing line if we have nothing */ + printf("\n"); + + for ( cpu = 0; cpu < max_cpu_nr; cpu += physinfo.threads_per_core ) + { + if ( fetch_dts_temp(xc_handle, cpu, false, &temp) ) + continue; + + has_data = true; + printf("CPU%d: %d°C\n", cpu, temp); + } + + if ( !has_data ) + printf("No data\n"); +} + void disable_turbo_mode(int argc, char *argv[]) { int cpuid = -1; @@ -XXX,XX +XXX,XX @@ struct { { "set-max-cstate", set_max_cstate_func}, { "enable-turbo-mode", enable_turbo_mode }, { "disable-turbo-mode", disable_turbo_mode }, + { "get-intel-temp", get_intel_temp }, }; int main(int argc, char *argv[]) { int i, ret = 0; - xc_physinfo_t physinfo; int nr_matches = 0; int matches_main_options[ARRAY_SIZE(main_options)]; -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
The idea here is to expose the DTS sensors through XENPF_resource_op and expose it for the user through xenpm. v4: - reuse original cpu-policy patch - remove xenpm building on non-x86 - add changelog notes - reviewed xc_resource_op return code handling - only print missing MSR_TEMPERATURE_TARGET message once - formatting changes v3: - use msr-index.h instead of adding defines to MSRs in xenpm v2: - moved userland part to xenpm - use cpu policy infrastructure instead of inline cpuid_* Jan Beulich (1): x86/cpu-policy: define bits of leaf 6 Teddy Astie (3): xenpm: Don't build outside of x86 x86/platform: Expose DTS sensors MSR xenpm: Add get-intel-temp subcommand CHANGELOG.md | 6 ++ tools/misc/Makefile | 2 +- tools/misc/xenpm.c | 113 ++++++++++++++++++++++++++- xen/arch/x86/include/asm/msr-index.h | 3 + xen/arch/x86/platform_hypercall.c | 6 ++ xen/include/xen/lib/x86/cpu-policy.h | 27 ++++++- 6 files changed, 154 insertions(+), 3 deletions(-) -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
From: Jan Beulich <jbeulich@suse.com> ... as far as we presently use them in the codebase. Signed-off-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Teddy Astie <teddy.astie@vates.tech> --- I don't know to which extend Reviewed-by applies as I only applied Andrew's proposal. xen/include/xen/lib/x86/cpu-policy.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/xen/include/xen/lib/x86/cpu-policy.h b/xen/include/xen/lib/x86/cpu-policy.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/xen/lib/x86/cpu-policy.h +++ b/xen/include/xen/lib/x86/cpu-policy.h @@ -XXX,XX +XXX,XX @@ struct cpu_policy uint64_t :64, :64; /* Leaf 0x3 - PSN. */ uint64_t :64, :64; /* Leaf 0x4 - Structured Cache. */ uint64_t :64, :64; /* Leaf 0x5 - MONITOR. */ - uint64_t :64, :64; /* Leaf 0x6 - Therm/Perf. */ + + /* Leaf 0x6 - Therm/Perf. */ + bool :1, + turbo:1, + arat:1, + :1, + :1, + :1, + :1, + hwp:1, + hwp_notification:1, + hwp_activity_window:1, + hwp_epp:1, + hwp_plr:1, + :1, + hdc:1, + :1, + :1, + hwp_peci:1, + :1, + :1, + hw_feedback:1; + uint32_t :32; /* b */ + bool aperfmperf:1; + uint32_t :32; /* d */ + uint64_t :64, :64; /* Leaf 0x7 - Structured Features. */ uint64_t :64, :64; /* Leaf 0x8 - rsvd */ uint64_t :64, :64; /* Leaf 0x9 - DCA */ -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
xenpm doesn't provide any interesting usable features outside of x86, skip building it if we are not x86. Suggested-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Teddy Astie <teddy.astie@vates.tech> --- CHANGELOG.md | 3 +++ tools/misc/Makefile | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index XXXXXXX..XXXXXXX 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -XXX,XX +XXX,XX @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) deprecated in Xen 4.7 and noted not to work correctly with AMD CPUs from 2011 onwards. + - Removed xenpm on non-x86 platforms as it doesn't actually provide anything + useful outside of x86. + ## [4.21.0](https://xenbits.xenproject.org/gitweb/?p=xen.git;a=shortlog;h=RELEASE-4.21.0) - 2025-11-19 ### Changed diff --git a/tools/misc/Makefile b/tools/misc/Makefile index XXXXXXX..XXXXXXX 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -XXX,XX +XXX,XX @@ INSTALL_SBIN-$(CONFIG_X86) += xen-lowmemd INSTALL_SBIN-$(CONFIG_X86) += xen-mceinj INSTALL_SBIN-$(CONFIG_X86) += xen-memshare INSTALL_SBIN-$(CONFIG_X86) += xen-mfndump +INSTALL_SBIN-$(CONFIG_X86) += xenpm INSTALL_SBIN-$(CONFIG_X86) += xen-ucode INSTALL_SBIN-$(CONFIG_X86) += xen-vmtrace INSTALL_SBIN += xencov INSTALL_SBIN += xenhypfs INSTALL_SBIN += xenlockprof INSTALL_SBIN += xenperf -INSTALL_SBIN += xenpm INSTALL_SBIN += xenwatchdogd INSTALL_SBIN += xen-access INSTALL_SBIN += xen-livepatch -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
Intel provide CPU sensors through "DTS" MSRs. As these MSR are core-specific (or package-specific), we can't reliably fetch them from Dom0 directly. Expose these MSR (if supported) through XENPF_resource_op so that it is accessible through hypercall. Suggested-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Teddy Astie <teddy.astie@vates.tech> --- xen/arch/x86/include/asm/msr-index.h | 3 +++ xen/arch/x86/platform_hypercall.c | 6 ++++++ xen/include/xen/lib/x86/cpu-policy.h | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/asm/msr-index.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/include/asm/msr-index.h +++ b/xen/arch/x86/include/asm/msr-index.h @@ -XXX,XX +XXX,XX @@ #define MCU_OPT_CTRL_GDS_MIT_DIS (_AC(1, ULL) << 4) #define MCU_OPT_CTRL_GDS_MIT_LOCK (_AC(1, ULL) << 5) +#define MSR_TEMPERATURE_TARGET 0x000001a2 +#define MSR_PACKAGE_THERM_STATUS 0x000001b1 + #define MSR_FRED_RSP_SL0 0x000001cc #define MSR_FRED_RSP_SL1 0x000001cd #define MSR_FRED_RSP_SL2 0x000001ce diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -XXX,XX +XXX,XX @@ #include <asm/current.h> #include <public/platform.h> #include <acpi/cpufreq/processor_perf.h> +#include <asm/cpu-policy.h> #include <asm/edd.h> #include <asm/microcode.h> #include <asm/mtrr.h> @@ -XXX,XX +XXX,XX @@ static bool msr_read_allowed(unsigned int msr) case MSR_MCU_OPT_CTRL: return cpu_has_srbds_ctrl; + + case MSR_IA32_THERM_STATUS: + case MSR_TEMPERATURE_TARGET: + case MSR_PACKAGE_THERM_STATUS: + return host_cpu_policy.basic.dts; } if ( ppin_msr && msr == ppin_msr ) diff --git a/xen/include/xen/lib/x86/cpu-policy.h b/xen/include/xen/lib/x86/cpu-policy.h index XXXXXXX..XXXXXXX 100644 --- a/xen/include/xen/lib/x86/cpu-policy.h +++ b/xen/include/xen/lib/x86/cpu-policy.h @@ -XXX,XX +XXX,XX @@ struct cpu_policy uint64_t :64, :64; /* Leaf 0x5 - MONITOR. */ /* Leaf 0x6 - Therm/Perf. */ - bool :1, + bool dts:1, turbo:1, arat:1, :1, -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech
get-intel-temp allows querying the per-core CPU temperature and per-package one on Intel processors (as usual Dom0 drivers cannot work due to misalignment between Dom0 vCPU and pCPUs). Signed-off-by: Teddy Astie <teddy.astie@vates.tech> --- CHANGELOG.md | 3 ++ tools/misc/xenpm.c | 113 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index XXXXXXX..XXXXXXX 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -XXX,XX +XXX,XX @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Changed ### Added + - On x86: + - Introduce get-intel-temp to xenpm to query CPU temperatures on Intel + platforms. ### Removed - On x86: diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c index XXXXXXX..XXXXXXX 100644 --- a/tools/misc/xenpm.c +++ b/tools/misc/xenpm.c @@ -XXX,XX +XXX,XX @@ #include <xen-tools/common-macros.h> +#include <xen/asm/msr-index.h> + #define MAX_PKG_RESIDENCIES 12 #define MAX_CORE_RESIDENCIES 8 static xc_interface *xc_handle; static unsigned int max_cpu_nr; +static xc_physinfo_t physinfo; /* help message */ void show_help(void) @@ -XXX,XX +XXX,XX @@ void show_help(void) " units default to \"us\" if unspecified.\n" " truncates un-representable values.\n" " 0 lets the hardware decide.\n" + " get-intel-temp [cpuid] get Intel CPU temperature of <cpuid> or all\n" " start [seconds] start collect Cx/Px statistics,\n" " output after CTRL-C or SIGINT or several seconds.\n" " enable-turbo-mode [cpuid] enable Turbo Mode for processors that support it.\n" @@ -XXX,XX +XXX,XX @@ void enable_turbo_mode(int argc, char *argv[]) errno, strerror(errno)); } +static int fetch_dts_temp(xc_interface *xch, uint32_t cpu, bool package, int *temp) +{ + xc_resource_entry_t entries[] = { + { .idx = package ? MSR_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS }, + { .idx = MSR_TEMPERATURE_TARGET }, + }; + struct xc_resource_op ops = { + .cpu = cpu, + .entries = entries, + .nr_entries = ARRAY_SIZE(entries), + }; + int tjmax; + + int ret = xc_resource_op(xch, 1, &ops); + + switch ( ret ) + { + case -1: + /* xc_resource_op returns -1 in out of memory scenarios */ + return -ENOMEM; + case 0: + /* This CPU isn't online or can't query this MSR */ + return -ENODATA; + case 1: + { + /* + * The CPU doesn't support MSR_TEMPERATURE_TARGET, we assume it's 100 + * which is correct aside a few selected Atom CPUs. Check Linux + * kernel's coretemp.c for more information. + */ + static bool has_reported_once = false; + + if ( !has_reported_once ) + { + fprintf(stderr, "MSR_TEMPERATURE_TARGET is not supported, assume " + "tjmax = 100, readings may be incorrect.\n"); + has_reported_once = true; + } + + tjmax = 100; + break; + } + case 2: + { + tjmax = (entries[1].val >> 16) & 0xff; + break; + } + default: + if ( ret > 0 ) + { + fprintf(stderr, "Got unexpected xc_resource_op return value: %d", + ret); + return -EINVAL; + } + return ret; + } + + *temp = tjmax - ((entries[0].val >> 16) & 0xff); + return 0; +} + +static void get_intel_temp(int argc, char *argv[]) +{ + int temp = -1, cpu = -1; + unsigned int socket; + bool has_data = false; + + if ( argc > 0 ) + parse_cpuid(argv[0], &cpu); + + if ( cpu != -1 ) + { + if ( !fetch_dts_temp(xc_handle, cpu, false, &temp) ) + printf("CPU%d: %d°C\n", cpu, temp); + else + printf("No data\n"); + return; + } + + /* Per socket measurement */ + for ( socket = 0, cpu = 0; cpu < max_cpu_nr; + socket++, cpu += physinfo.cores_per_socket * physinfo.threads_per_core ) + { + if ( !fetch_dts_temp(xc_handle, cpu, true, &temp) ) + { + has_data = true; + printf("Package%u: %d°C\n", socket, temp); + } + } + + if ( has_data ) + /* Avoid inserting a trailing line if we have nothing */ + printf("\n"); + + for ( cpu = 0; cpu < max_cpu_nr; cpu += physinfo.threads_per_core ) + { + if ( fetch_dts_temp(xc_handle, cpu, false, &temp) ) + continue; + + has_data = true; + printf("CPU%d: %d°C\n", cpu, temp); + } + + if ( !has_data ) + printf("No data\n"); +} + void disable_turbo_mode(int argc, char *argv[]) { int cpuid = -1; @@ -XXX,XX +XXX,XX @@ struct { { "set-max-cstate", set_max_cstate_func}, { "enable-turbo-mode", enable_turbo_mode }, { "disable-turbo-mode", disable_turbo_mode }, + { "get-intel-temp", get_intel_temp }, }; int main(int argc, char *argv[]) { int i, ret = 0; - xc_physinfo_t physinfo; int nr_matches = 0; int matches_main_options[ARRAY_SIZE(main_options)]; -- 2.51.2 -- Teddy Astie | Vates XCP-ng Developer XCP-ng & Xen Orchestra - Vates solutions web: https://vates.tech