lib/Kernel/cpu.pm

SYNOPSIS

CPU helpers for kernel tests.

To run lscpu only one time, get the data with lscpu_info() and give it to the other helpers:

my $info = lscpu_info();
my $model = get_cpu_model($info);
my $count = get_cpu_count($info);

If no data is given, each helper runs lscpu again.

lscpu_info

my $info = lscpu_info();

Runs LC_ALL=C lscpu on the SUT and returns a hash reference of field name to value, for example $info->{'Model name'}. The leading indentation of new lscpu versions is ignored. If a field occurs more than one time, the first value is kept.

get_cpu_model

my $model = get_cpu_model([$info]);

Returns the CPU model name, from the lscpu Model name field. If it is not available (for example on s390x), returns the Machine type, then the Model field. Returns undef if none is available.

get_cpu_count

my $count = get_cpu_count([$info]);

Returns the number of online CPUs, from the lscpu On-line CPU(s) list field. Offline CPUs are not counted.

get_online_cpus

my @cpus = get_online_cpus();

Returns the list of online CPU numbers, from /sys/devices/system/cpu/online.

get_offline_cpus

my @cpus = get_offline_cpus();

Returns the list of offline CPU numbers, from /sys/devices/system/cpu/offline. These CPUs are present or possible, but not online. Returns an empty list if all CPUs are online.

get_present_cpus

my @cpus = get_present_cpus();

Returns the list of present CPU numbers, from /sys/devices/system/cpu/present. These are the CPUs that the system has, online or offline.

get_cpu_topology

my $topology = get_cpu_topology([$info]);

Returns a hash reference with the keys sockets, cores_per_socket, threads_per_core and numa_nodes, from lscpu. A value is undef if lscpu does not show it on this architecture (for example, s390x shows sockets per book instead of sockets).

get_cpu_map

my $map = get_cpu_map();

Returns a hash reference of the CPU number to a hash reference with the keys socket, node (NUMA node) and online (1 or 0), from lscpu -a -p. Offline CPUs are included. socket or node is undef if lscpu does not show it, for example node on a system without NUMA.

Use it to group per-CPU values by socket or NUMA node:

my $map = get_cpu_map();
my %sockets = map { $map->{$_}{socket} => 1 } grep { $map->{$_}{online} } keys %$map;

get_cpu_flags

my @flags = get_cpu_flags([$info]);

Returns the list of CPU flags, from the lscpu Flags field. Returns an empty list if lscpu shows no flags.

has_cpu_flag

has_cpu_flag($flag, [$info]);

Returns true if the CPU has the flag $flag, for example arch_perfmon.

get_cpu_vulnerabilities

my $vulns = get_cpu_vulnerabilities();

Reads the files in /sys/devices/system/cpu/vulnerabilities/ on the SUT and returns a hash reference of vulnerability name to status, for example { retbleed => 'Mitigation: IBRS' }. Returns an empty hash reference if the directory does not exist.

has_hw_pmu

has_hw_pmu();

Checks whether a hardware Performance Monitoring Unit (PMU) is available, with perf stat -e cycles. The perf package must be installed.

Returns true if the cycles hardware event is counted. Returns false if it is not supported or not counted, for example in a virtual machine without a virtual PMU.

nmi_count

my $count = nmi_count();

Returns the sum of the NMI counters of all CPUs from /proc/interrupts. Returns 0 if there is no NMI line.

The meaning of the NMI line is architecture specific: on x86_64 it includes the PMU interrupts, but on ppc64le it counts System Reset interrupts and on s390x Machine Check interrupts.