analyze: introduce cpu-features command
This may be useful when configuring the ConditionCPUFeature= setting.
This commit is contained in:
@@ -224,6 +224,12 @@
|
||||
<arg choice="plain">architectures</arg>
|
||||
<arg choice="opt" rep="repeat"><replaceable>NAME</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-analyze</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="plain">cpu-features</arg>
|
||||
<arg choice="opt" rep="repeat"><replaceable>NAME</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-analyze</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
@@ -1159,6 +1165,30 @@ x86-64 native</programlisting>
|
||||
</example>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><command>systemd-analyze cpu-features <optional><replaceable>NAME</replaceable>...</optional></command></title>
|
||||
|
||||
<para>Lists all known CPU features for the system's CPU architecture, indicating which of them are
|
||||
supported. The listed feature names are those understood by <varname>ConditionCPUFeature=</varname>;
|
||||
see <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. If one or more feature names are specified, only those are listed.</para>
|
||||
|
||||
<para>The command is currently supported only on arm64, x86, and x86_64 systems.</para>
|
||||
|
||||
<example>
|
||||
<title>Table output on an x86_64 system</title>
|
||||
<programlisting>$ systemd-analyze cpu-features
|
||||
NAME SUPPORT
|
||||
abm ✓
|
||||
adx ✓
|
||||
aes ✓
|
||||
apic ✓
|
||||
avx ✓
|
||||
avx2 ✓
|
||||
…</programlisting>
|
||||
</example>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><command>systemd-analyze smbios11</command></title>
|
||||
|
||||
|
||||
@@ -2058,6 +2058,11 @@
|
||||
among others. For the full list, see the documentation on
|
||||
<ulink url="https://docs.kernel.org/arch/arm64/elf_hwcaps.html">ARM64 ELF hwcaps</ulink>.</para>
|
||||
|
||||
<para>See
|
||||
<citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<command>cpu-features</command> command for the complete list of known CPU features for the system.
|
||||
</para>
|
||||
|
||||
<para>To avoid ambiguities in mixed-architecture fleets, the value can be prefixed
|
||||
with the architecture name using the form <literal>ARCH.FEATURE</literal>. If the
|
||||
architecture prefix does not match the running system, the condition evaluates
|
||||
|
||||
@@ -56,6 +56,10 @@ __get_architectures() {
|
||||
systemd-analyze --no-legend --no-pager architectures 2>/dev/null | { while read -r a b; do echo " $a"; done; }
|
||||
}
|
||||
|
||||
__get_cpu_features() {
|
||||
systemd-analyze --no-legend --no-pager cpu-features 2>/dev/null | { while read -r a b; do echo " $a"; done; }
|
||||
}
|
||||
|
||||
__get_filesystem_sets() {
|
||||
local line
|
||||
systemd-analyze filesystems --no-pager 2>/dev/null | while IFS= read -r line; do
|
||||
@@ -91,6 +95,7 @@ _systemd_analyze() {
|
||||
[DLOPEN_METADATA]='dlopen-metadata'
|
||||
[PLOT]='plot'
|
||||
[ARCHITECTURES]='architectures'
|
||||
[CPU_FEATURES]='cpu-features'
|
||||
[FDSTORE]='fdstore'
|
||||
[CAPABILITY]='capability'
|
||||
[TRANSIENT_SETTINGS]='transient-settings'
|
||||
@@ -250,6 +255,13 @@ _systemd_analyze() {
|
||||
comps=$( __get_architectures )
|
||||
fi
|
||||
|
||||
elif __contains_word "$verb" ${VERBS[CPU_FEATURES]}; then
|
||||
if [[ $cur = -* ]]; then
|
||||
comps='--help --version --no-pager --json=off --json=pretty --json=short --no-legend'
|
||||
else
|
||||
comps=$( __get_cpu_features )
|
||||
fi
|
||||
|
||||
elif __contains_word "$verb" ${VERBS[FDSTORE]}; then
|
||||
if [[ $cur = -* ]]; then
|
||||
comps='--help --version --system --user --global -H --host -M --machine --no-pager --json=off --json=pretty --json=short --root --image'
|
||||
|
||||
@@ -52,6 +52,13 @@
|
||||
_describe -t architectures 'architectures' _architectures || compadd "$@"
|
||||
}
|
||||
|
||||
(( $+functions[_systemd-analyze_cpu-features] )) ||
|
||||
_systemd-analyze_cpu-features() {
|
||||
local -a _features
|
||||
_features=( $(systemd-analyze --quiet --no-pager --no-legend cpu-features 2>/dev/null | { while read -r a b; do echo " $a"; done; }) )
|
||||
_describe -t features 'cpu features' _features || compadd "$@"
|
||||
}
|
||||
|
||||
(( $+functions[_systemd-analyze_plot] )) ||
|
||||
_systemd-analyze_plot() {
|
||||
local -a _options
|
||||
@@ -95,6 +102,7 @@
|
||||
'has-tpm2:Report whether TPM2 support is available'
|
||||
'transient-settings:List transient settings for unit types'
|
||||
'architectures:List known architectures'
|
||||
'cpu-features:List known CPU features'
|
||||
'smbios11:List strings passed via SMBIOS Type #11'
|
||||
'chid:List local CHIDs'
|
||||
'compare-versions:Compare two version strings'
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "analyze.h"
|
||||
#include "analyze-cpu-features.h"
|
||||
#include "ansi-color.h"
|
||||
#include "architecture.h"
|
||||
#include "format-table.h"
|
||||
#include "log.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "virt.h"
|
||||
|
||||
static int add_feature(Table *table, const char *feature, bool known) {
|
||||
int r;
|
||||
|
||||
assert(table);
|
||||
assert(feature);
|
||||
|
||||
if (known) {
|
||||
bool has = has_cpu_with_flag(feature);
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, feature,
|
||||
TABLE_BOOLEAN_CHECKMARK, has,
|
||||
TABLE_SET_COLOR, ansi_highlight_green_red(has));
|
||||
} else
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, feature,
|
||||
TABLE_TRISTATE, -1,
|
||||
TABLE_SET_COLOR, ansi_grey());
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int verb_cpu_features(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
int r;
|
||||
|
||||
_cleanup_strv_free_ char **features = NULL;
|
||||
r = cpu_known_features(&features);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
if (strv_isempty(features))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"No known CPU features for the %s architecture.",
|
||||
architecture_to_string(native_architecture()));
|
||||
|
||||
_cleanup_(table_unrefp) Table *table = table_new("name", "support");
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
(void) table_set_sort(table, (size_t) 0);
|
||||
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
|
||||
|
||||
char **args = strv_skip(argv, 1);
|
||||
if (args)
|
||||
STRV_FOREACH(feat, args) {
|
||||
_cleanup_free_ char *lower = strdup(*feat);
|
||||
if (!lower)
|
||||
return log_oom();
|
||||
|
||||
ascii_strlower(lower);
|
||||
r = add_feature(table, lower, strv_contains(features, lower));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
else
|
||||
STRV_FOREACH(feat, features) {
|
||||
r = add_feature(table, *feat, /* known= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return table_print_with_pager(table, arg_json_format_flags, arg_pager_flags, arg_legend);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
int verb_cpu_features(int argc, char *argv[], uintptr_t _data, void *userdata);
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "analyze-chid.h"
|
||||
#include "analyze-compare-versions.h"
|
||||
#include "analyze-condition.h"
|
||||
#include "analyze-cpu-features.h"
|
||||
#include "analyze-critical-chain.h"
|
||||
#include "analyze-dlopen-metadata.h"
|
||||
#include "analyze-dot.h"
|
||||
@@ -243,6 +244,8 @@ VERB_SCOPE(, verb_filesystems, "filesystems", "[NAME...]\0", VERB_ANY, VERB_ANY,
|
||||
"List known filesystems");
|
||||
VERB_SCOPE(, verb_architectures, "architectures", "[NAME...]\0", VERB_ANY, VERB_ANY, 0,
|
||||
"List known architectures");
|
||||
VERB_SCOPE(, verb_cpu_features, "cpu-features", "[NAME...]\0", VERB_ANY, VERB_ANY, 0,
|
||||
"List known CPU features");
|
||||
VERB_SCOPE(, verb_smbios11, "smbios11", NULL, VERB_ANY, 1, 0,
|
||||
"List strings passed via SMBIOS Type #11");
|
||||
VERB_SCOPE(, verb_chid, "chid", NULL, VERB_ANY, VERB_ANY, 0,
|
||||
@@ -578,9 +581,12 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) {
|
||||
"Option --offline= requires one or more units to perform a security review.");
|
||||
|
||||
if (arg_json_format_flags != SD_JSON_FORMAT_OFF &&
|
||||
!STRPTR_IN_SET(verb, "security", "inspect-elf", "dlopen-metadata", "plot", "fdstore", "pcrs", "nvpcrs", "architectures", "capability", "exit-status", "chid", "blame", "identify-tpm2"))
|
||||
!STRPTR_IN_SET(verb,
|
||||
"security", "inspect-elf", "dlopen-metadata", "plot", "fdstore", "pcrs", "nvpcrs",
|
||||
"architectures", "cpu-features", "capability", "exit-status", "chid", "blame",
|
||||
"identify-tpm2"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --json= is only supported for security, inspect-elf, dlopen-metadata, plot, fdstore, pcrs, nvpcrs, architectures, capability, exit-status, chid, blame, identify-tpm2 right now.");
|
||||
"Option --json= is only supported for security, inspect-elf, dlopen-metadata, plot, fdstore, pcrs, nvpcrs, architectures, cpu-features, capability, exit-status, chid, blame, identify-tpm2 right now.");
|
||||
|
||||
if (arg_threshold != 100 && !streq_ptr(verb, "security"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
|
||||
@@ -9,6 +9,7 @@ systemd_analyze_sources = files(
|
||||
'analyze-chid.c',
|
||||
'analyze-compare-versions.c',
|
||||
'analyze-condition.c',
|
||||
'analyze-cpu-features.c',
|
||||
'analyze-critical-chain.c',
|
||||
'analyze-dlopen-metadata.c',
|
||||
'analyze-dot.c',
|
||||
|
||||
@@ -1137,6 +1137,51 @@ bool has_cpu_with_flag(const char *flag) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int cpu_known_features(char ***ret) {
|
||||
assert(ret);
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static const struct {
|
||||
const struct cpuid_table_entry *table;
|
||||
size_t n_entries;
|
||||
} tables[] = {
|
||||
{ leaf1_edx, ELEMENTSOF(leaf1_edx), },
|
||||
{ leaf1_ecx, ELEMENTSOF(leaf1_ecx), },
|
||||
{ leaf7_ebx, ELEMENTSOF(leaf7_ebx), },
|
||||
{ leaf81_ecx, ELEMENTSOF(leaf81_ecx), },
|
||||
{ leaf81_edx, ELEMENTSOF(leaf81_edx), },
|
||||
{ leaf87_edx, ELEMENTSOF(leaf87_edx), },
|
||||
};
|
||||
#elif defined(__aarch64__)
|
||||
static const struct {
|
||||
const struct hwcap_table_entry *table;
|
||||
size_t n_entries;
|
||||
} tables[] = {
|
||||
{ hwcap, ELEMENTSOF(hwcap), },
|
||||
{ hwcap2, ELEMENTSOF(hwcap2), },
|
||||
{ hwcap3, ELEMENTSOF(hwcap3), },
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
|
||||
_cleanup_strv_free_ char **features = NULL;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
|
||||
FOREACH_ELEMENT(table, tables)
|
||||
FOREACH_ARRAY(i, table->table, table->n_entries) {
|
||||
r = strv_extend_with_size(&features, &n, i->name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(features);
|
||||
#else
|
||||
*ret = NULL;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
|
||||
[VIRTUALIZATION_NONE] = "none",
|
||||
[VIRTUALIZATION_KVM] = "kvm",
|
||||
|
||||
@@ -64,3 +64,4 @@ int running_in_chroot(void);
|
||||
|
||||
DECLARE_STRING_TABLE_LOOKUP(virtualization, Virtualization);
|
||||
bool has_cpu_with_flag(const char *flag);
|
||||
int cpu_known_features(char ***ret);
|
||||
|
||||
@@ -1125,6 +1125,16 @@ systemd-analyze architectures x86-64
|
||||
systemd-analyze architectures native
|
||||
systemd-analyze architectures uname
|
||||
|
||||
if systemd-analyze --no-legend architectures native | grep -E '^(x86|x86-64|arm64|arm64-be)[[:space:]]' >/dev/null; then
|
||||
rc=0
|
||||
else
|
||||
rc=1
|
||||
fi
|
||||
assert_rc "$rc" systemd-analyze cpu-features
|
||||
assert_rc "$rc" systemd-analyze cpu-features --json=pretty
|
||||
assert_rc "$rc" systemd-analyze cpu-features foo hoge fpu fp
|
||||
assert_rc "$rc" systemd-analyze cpu-features --json=pretty foo hoge fpu fp avx
|
||||
|
||||
systemd-analyze smbios11
|
||||
systemd-analyze smbios11 -q
|
||||
|
||||
|
||||
Reference in New Issue
Block a user