Add support for aarch64 CPUFeatures (#42902)
Extend real_has_cpu_with_flag to support aarch64 CPU Features using hwcaps. With this PR, users can find out if their Arm system supports architecture-specific features such as BTI as follows: ``` $ systemd-analyze condition 'ConditionCPUFeature=bti' ```
This commit is contained in:
+25
-5
@@ -1988,11 +1988,10 @@
|
||||
<varlistentry>
|
||||
<term><varname>ConditionCPUFeature=</varname></term>
|
||||
|
||||
<listitem><para>Verify that a given CPU feature is available via the <literal>CPUID</literal>
|
||||
instruction. This condition only does something on i386 and x86-64 processors. On other
|
||||
processors it is assumed that the CPU does not support the given feature. It checks the leaves
|
||||
<literal>1</literal>, <literal>7</literal>, <literal>0x80000001</literal>, and
|
||||
<literal>0x80000007</literal>. Valid values are:
|
||||
<listitem><para>On i386 and x86-64, verify that a given CPU feature is available via the
|
||||
<literal>CPUID</literal> instruction. It checks the leaves <literal>1</literal>,
|
||||
<literal>7</literal>, <literal>0x80000001</literal>, and <literal>0x80000007</literal>. Valid
|
||||
values are:
|
||||
<literal>fpu</literal>,
|
||||
<literal>vme</literal>,
|
||||
<literal>de</literal>,
|
||||
@@ -2045,6 +2044,27 @@
|
||||
<literal>abm</literal>,
|
||||
<literal>constant_tsc</literal>.</para>
|
||||
|
||||
<para>On arm64, valid values are the corresponding arm64 feature names,
|
||||
such as
|
||||
<literal>asimd</literal>,
|
||||
<literal>paca</literal>,
|
||||
<literal>pacg</literal>,
|
||||
<literal>bti</literal>,
|
||||
<literal>mte</literal>,
|
||||
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>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
|
||||
to false. For example, one can specify <literal>arm64.bti</literal> on arm64
|
||||
systems to check if <literal>bti</literal> is supported. In this example,
|
||||
<literal>ConditionCPUFeature=arm64.bti</literal> and
|
||||
<literal>ConditionCPUFeature=bti</literal> are functionally equivalent.
|
||||
See <varname>ConditionArchitecture=</varname> for valid architecture names.</para>
|
||||
|
||||
<para>On architectures other than x86 and arm64, it is assumed that the CPU does not support the given feature.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v248"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+178
-2
@@ -3,6 +3,9 @@
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
#if defined(__aarch64__)
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <threads.h>
|
||||
#include <unistd.h>
|
||||
@@ -951,9 +954,182 @@ static bool real_has_cpu_with_flag(const char *flag) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__)
|
||||
struct hwcap_table_entry {
|
||||
uint64_t flag_mask;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct hwcap_table_entry hwcap[] = {
|
||||
{ HWCAP_FP, "fp" },
|
||||
{ HWCAP_ASIMD, "asimd" },
|
||||
{ HWCAP_EVTSTRM, "evtstrm" },
|
||||
{ HWCAP_AES, "aes" },
|
||||
{ HWCAP_PMULL, "pmull" },
|
||||
{ HWCAP_SHA1, "sha1" },
|
||||
{ HWCAP_SHA2, "sha2" },
|
||||
{ HWCAP_CRC32, "crc32" },
|
||||
{ HWCAP_ATOMICS, "atomics" },
|
||||
{ HWCAP_FPHP, "fphp" },
|
||||
{ HWCAP_ASIMDHP, "asimdhp" },
|
||||
{ HWCAP_CPUID, "cpuid" },
|
||||
{ HWCAP_ASIMDRDM, "asimdrdm" },
|
||||
{ HWCAP_JSCVT, "jscvt" },
|
||||
{ HWCAP_FCMA, "fcma" },
|
||||
{ HWCAP_LRCPC, "lrcpc" },
|
||||
{ HWCAP_DCPOP, "dcpop" },
|
||||
{ HWCAP_SHA3, "sha3" },
|
||||
{ HWCAP_SM3, "sm3" },
|
||||
{ HWCAP_SM4, "sm4" },
|
||||
{ HWCAP_ASIMDDP, "asimddp" },
|
||||
{ HWCAP_SHA512, "sha512" },
|
||||
{ HWCAP_SVE, "sve" },
|
||||
{ HWCAP_ASIMDFHM, "asimdfhm" },
|
||||
{ HWCAP_DIT, "dit" },
|
||||
{ HWCAP_USCAT, "uscat" },
|
||||
{ HWCAP_ILRCPC, "ilrcpc" },
|
||||
{ HWCAP_FLAGM, "flagm" },
|
||||
{ HWCAP_SSBS, "ssbs" },
|
||||
{ HWCAP_SB, "sb" },
|
||||
{ HWCAP_PACA, "paca" },
|
||||
{ HWCAP_PACG, "pacg" },
|
||||
{ HWCAP_GCS, "gcs" },
|
||||
{ HWCAP_CMPBR, "cmpbr" },
|
||||
{ HWCAP_FPRCVT, "fprcvt" },
|
||||
{ HWCAP_F8MM8, "f8mm8" },
|
||||
{ HWCAP_F8MM4, "f8mm4" },
|
||||
{ HWCAP_SVE_F16MM, "svef16mm" },
|
||||
{ HWCAP_SVE_ELTPERM, "sveeltperm" },
|
||||
{ HWCAP_SVE_AES2, "sveaes2" },
|
||||
{ HWCAP_SVE_BFSCALE, "svebfscale" },
|
||||
{ HWCAP_SVE2P2, "sve2p2" },
|
||||
{ HWCAP_SME2P2, "sme2p2" },
|
||||
{ HWCAP_SME_SBITPERM, "smesbitperm" },
|
||||
{ HWCAP_SME_AES, "smeaes" },
|
||||
{ HWCAP_SME_SFEXPA, "smesfexpa" },
|
||||
{ HWCAP_SME_STMOP, "smestmop" },
|
||||
{ HWCAP_SME_SMOP4, "smesmop4" },
|
||||
};
|
||||
|
||||
static const struct hwcap_table_entry hwcap2[] = {
|
||||
{ HWCAP2_DCPODP, "dcpodp" },
|
||||
{ HWCAP2_SVE2, "sve2" },
|
||||
{ HWCAP2_SVEAES, "sveaes" },
|
||||
{ HWCAP2_SVEPMULL, "svepmull" },
|
||||
{ HWCAP2_SVEBITPERM, "svebitperm" },
|
||||
{ HWCAP2_SVESHA3, "svesha3" },
|
||||
{ HWCAP2_SVESM4, "svesm4" },
|
||||
{ HWCAP2_FLAGM2, "flagm2" },
|
||||
{ HWCAP2_FRINT, "frint" },
|
||||
{ HWCAP2_SVEI8MM, "svei8mm" },
|
||||
{ HWCAP2_SVEF32MM, "svef32mm" },
|
||||
{ HWCAP2_SVEF64MM, "svef64mm" },
|
||||
{ HWCAP2_SVEBF16, "svebf16" },
|
||||
{ HWCAP2_I8MM, "i8mm" },
|
||||
{ HWCAP2_BF16, "bf16" },
|
||||
{ HWCAP2_DGH, "dgh" },
|
||||
{ HWCAP2_RNG, "rng" },
|
||||
{ HWCAP2_BTI, "bti" },
|
||||
{ HWCAP2_MTE, "mte" },
|
||||
{ HWCAP2_ECV, "ecv" },
|
||||
{ HWCAP2_AFP, "afp" },
|
||||
{ HWCAP2_RPRES, "rpres" },
|
||||
{ HWCAP2_MTE3, "mte3" },
|
||||
{ HWCAP2_SME, "sme" },
|
||||
{ HWCAP2_SME_I16I64, "smei16i64" },
|
||||
{ HWCAP2_SME_F64F64, "smef64f64" },
|
||||
{ HWCAP2_SME_I8I32, "smei8i32" },
|
||||
{ HWCAP2_SME_F16F32, "smef16f32" },
|
||||
{ HWCAP2_SME_B16F32, "smeb16f32" },
|
||||
{ HWCAP2_SME_F32F32, "smef32f32" },
|
||||
{ HWCAP2_SME_FA64, "smefa64" },
|
||||
{ HWCAP2_WFXT, "wfxt" },
|
||||
{ HWCAP2_EBF16, "ebf16" },
|
||||
{ HWCAP2_SVE_EBF16, "sveebf16" },
|
||||
{ HWCAP2_CSSC, "cssc" },
|
||||
{ HWCAP2_RPRFM, "rprfm" },
|
||||
{ HWCAP2_SVE2P1, "sve2p1" },
|
||||
{ HWCAP2_SME2, "sme2" },
|
||||
{ HWCAP2_SME2P1, "sme2p1" },
|
||||
{ HWCAP2_SME_I16I32, "smei16i32" },
|
||||
{ HWCAP2_SME_BI32I32, "smebi32i32" },
|
||||
{ HWCAP2_SME_B16B16, "smeb16b16" },
|
||||
{ HWCAP2_SME_F16F16, "smef16f16" },
|
||||
{ HWCAP2_MOPS, "mops" },
|
||||
{ HWCAP2_HBC, "hbc" },
|
||||
{ HWCAP2_SVE_B16B16, "sveb16b16" },
|
||||
{ HWCAP2_LRCPC3, "lrcpc3" },
|
||||
{ HWCAP2_LSE128, "lse128" },
|
||||
{ HWCAP2_FPMR, "fpmr" },
|
||||
{ HWCAP2_LUT, "lut" },
|
||||
{ HWCAP2_FAMINMAX, "faminmax" },
|
||||
{ HWCAP2_F8CVT, "f8cvt" },
|
||||
{ HWCAP2_F8FMA, "f8fma" },
|
||||
{ HWCAP2_F8DP4, "f8dp4" },
|
||||
{ HWCAP2_F8DP2, "f8dp2" },
|
||||
{ HWCAP2_F8E4M3, "f8e4m3" },
|
||||
{ HWCAP2_F8E5M2, "f8e5m2" },
|
||||
{ HWCAP2_SME_LUTV2, "smelutv2" },
|
||||
{ HWCAP2_SME_F8F16, "smef8f16" },
|
||||
{ HWCAP2_SME_F8F32, "smef8f32" },
|
||||
{ HWCAP2_SME_SF8FMA, "smesf8fma" },
|
||||
{ HWCAP2_SME_SF8DP4, "smesf8dp4" },
|
||||
{ HWCAP2_SME_SF8DP2, "smesf8dp2" },
|
||||
{ HWCAP2_POE, "poe" },
|
||||
};
|
||||
|
||||
static const struct hwcap_table_entry hwcap3[] = {
|
||||
{ HWCAP3_MTE_FAR, "mtefar" },
|
||||
{ HWCAP3_MTE_STORE_ONLY, "mtestoreonly" },
|
||||
{ HWCAP3_LSFE, "lsfe" },
|
||||
{ HWCAP3_LS64, "ls64" },
|
||||
{ HWCAP3_SVE_B16MM, "sveb16mm" },
|
||||
{ HWCAP3_SVE2P3, "sve2p3" },
|
||||
{ HWCAP3_SME_LUT6, "smelut6" },
|
||||
{ HWCAP3_SME2P3, "sme2p3" },
|
||||
{ HWCAP3_F16MM, "f16mm" },
|
||||
{ HWCAP3_F16F32DOT, "f16f32dot" },
|
||||
{ HWCAP3_F16F32MM, "f16f32mm" },
|
||||
{ HWCAP3_SVE_LUT6, "svelut6" },
|
||||
};
|
||||
|
||||
static bool given_flag_in_hwcap_set(
|
||||
const char *flag,
|
||||
const struct hwcap_table_entry *set,
|
||||
size_t set_size,
|
||||
unsigned long val) {
|
||||
|
||||
assert(set);
|
||||
|
||||
for (size_t i = 0; i < set_size; i++)
|
||||
if ((set[i].flag_mask & val) && streq(flag, set[i].name))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool real_has_cpu_with_flag(const char *flag) {
|
||||
unsigned long val;
|
||||
|
||||
val = getauxval(AT_HWCAP);
|
||||
if (given_flag_in_hwcap_set(flag, hwcap, ELEMENTSOF(hwcap), val))
|
||||
return true;
|
||||
|
||||
val = getauxval(AT_HWCAP2);
|
||||
if (given_flag_in_hwcap_set(flag, hwcap2, ELEMENTSOF(hwcap2), val))
|
||||
return true;
|
||||
|
||||
val = getauxval(AT_HWCAP3);
|
||||
if (given_flag_in_hwcap_set(flag, hwcap3, ELEMENTSOF(hwcap3), val))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool has_cpu_with_flag(const char *flag) {
|
||||
/* CPUID is an x86 specific interface. Assume on all others that no CPUs have those flags. */
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/* Check the architecture-specific CPU feature interface when available. */
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
|
||||
return real_has_cpu_with_flag(flag);
|
||||
#else
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include_next <elf.h> /* IWYU pragma: export */
|
||||
|
||||
/* AT_HWCAP3 was added in glibc 2.39. */
|
||||
#ifndef AT_HWCAP3
|
||||
#define AT_HWCAP3 29
|
||||
#endif
|
||||
@@ -0,0 +1,229 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include_next <bits/hwcap.h> /* IWYU pragma: export */
|
||||
|
||||
/* All other capabilities are defined in glibc-2.34 / musl 1.2.6 or earlier */
|
||||
#if defined(__aarch64__)
|
||||
#ifndef HWCAP_GCS
|
||||
#define HWCAP_GCS (1UL << 32)
|
||||
#endif
|
||||
#ifndef HWCAP_CMPBR
|
||||
#define HWCAP_CMPBR (1UL << 33)
|
||||
#endif
|
||||
#ifndef HWCAP_FPRCVT
|
||||
#define HWCAP_FPRCVT (1UL << 34)
|
||||
#endif
|
||||
#ifndef HWCAP_F8MM8
|
||||
#define HWCAP_F8MM8 (1UL << 35)
|
||||
#endif
|
||||
#ifndef HWCAP_F8MM4
|
||||
#define HWCAP_F8MM4 (1UL << 36)
|
||||
#endif
|
||||
#ifndef HWCAP_SVE_F16MM
|
||||
#define HWCAP_SVE_F16MM (1UL << 37)
|
||||
#endif
|
||||
#ifndef HWCAP_SVE_ELTPERM
|
||||
#define HWCAP_SVE_ELTPERM (1UL << 38)
|
||||
#endif
|
||||
#ifndef HWCAP_SVE_AES2
|
||||
#define HWCAP_SVE_AES2 (1UL << 39)
|
||||
#endif
|
||||
#ifndef HWCAP_SVE_BFSCALE
|
||||
#define HWCAP_SVE_BFSCALE (1UL << 40)
|
||||
#endif
|
||||
#ifndef HWCAP_SVE2P2
|
||||
#define HWCAP_SVE2P2 (1UL << 41)
|
||||
#endif
|
||||
#ifndef HWCAP_SME2P2
|
||||
#define HWCAP_SME2P2 (1UL << 42)
|
||||
#endif
|
||||
#ifndef HWCAP_SME_SBITPERM
|
||||
#define HWCAP_SME_SBITPERM (1UL << 43)
|
||||
#endif
|
||||
#ifndef HWCAP_SME_AES
|
||||
#define HWCAP_SME_AES (1UL << 44)
|
||||
#endif
|
||||
#ifndef HWCAP_SME_SFEXPA
|
||||
#define HWCAP_SME_SFEXPA (1UL << 45)
|
||||
#endif
|
||||
#ifndef HWCAP_SME_STMOP
|
||||
#define HWCAP_SME_STMOP (1UL << 46)
|
||||
#endif
|
||||
#ifndef HWCAP_SME_SMOP4
|
||||
#define HWCAP_SME_SMOP4 (1UL << 47)
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP2_ECV
|
||||
#define HWCAP2_ECV (1 << 19)
|
||||
#endif
|
||||
#ifndef HWCAP2_AFP
|
||||
#define HWCAP2_AFP (1 << 20)
|
||||
#endif
|
||||
#ifndef HWCAP2_RPRES
|
||||
#define HWCAP2_RPRES (1 << 21)
|
||||
#endif
|
||||
#ifndef HWCAP2_MTE3
|
||||
#define HWCAP2_MTE3 (1 << 22)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME
|
||||
#define HWCAP2_SME (1 << 23)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_I16I64
|
||||
#define HWCAP2_SME_I16I64 (1 << 24)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_F64F64
|
||||
#define HWCAP2_SME_F64F64 (1 << 25)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_I8I32
|
||||
#define HWCAP2_SME_I8I32 (1 << 26)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_F16F32
|
||||
#define HWCAP2_SME_F16F32 (1 << 27)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_B16F32
|
||||
#define HWCAP2_SME_B16F32 (1 << 28)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_F32F32
|
||||
#define HWCAP2_SME_F32F32 (1 << 29)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_FA64
|
||||
#define HWCAP2_SME_FA64 (1 << 30)
|
||||
#endif
|
||||
#ifndef HWCAP2_WFXT
|
||||
#define HWCAP2_WFXT (1UL << 31)
|
||||
#endif
|
||||
#ifndef HWCAP2_EBF16
|
||||
#define HWCAP2_EBF16 (1UL << 32)
|
||||
#endif
|
||||
#ifndef HWCAP2_SVE_EBF16
|
||||
#define HWCAP2_SVE_EBF16 (1UL << 33)
|
||||
#endif
|
||||
#ifndef HWCAP2_CSSC
|
||||
#define HWCAP2_CSSC (1UL << 34)
|
||||
#endif
|
||||
#ifndef HWCAP2_RPRFM
|
||||
#define HWCAP2_RPRFM (1UL << 35)
|
||||
#endif
|
||||
#ifndef HWCAP2_SVE2P1
|
||||
#define HWCAP2_SVE2P1 (1UL << 36)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME2
|
||||
#define HWCAP2_SME2 (1UL << 37)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME2P1
|
||||
#define HWCAP2_SME2P1 (1UL << 38)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_I16I32
|
||||
#define HWCAP2_SME_I16I32 (1UL << 39)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_BI32I32
|
||||
#define HWCAP2_SME_BI32I32 (1UL << 40)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_B16B16
|
||||
#define HWCAP2_SME_B16B16 (1UL << 41)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_F16F16
|
||||
#define HWCAP2_SME_F16F16 (1UL << 42)
|
||||
#endif
|
||||
#ifndef HWCAP2_MOPS
|
||||
#define HWCAP2_MOPS (1UL << 43)
|
||||
#endif
|
||||
#ifndef HWCAP2_HBC
|
||||
#define HWCAP2_HBC (1UL << 44)
|
||||
#endif
|
||||
#ifndef HWCAP2_SVE_B16B16
|
||||
#define HWCAP2_SVE_B16B16 (1UL << 45)
|
||||
#endif
|
||||
#ifndef HWCAP2_LRCPC3
|
||||
#define HWCAP2_LRCPC3 (1UL << 46)
|
||||
#endif
|
||||
#ifndef HWCAP2_LSE128
|
||||
#define HWCAP2_LSE128 (1UL << 47)
|
||||
#endif
|
||||
#ifndef HWCAP2_FPMR
|
||||
#define HWCAP2_FPMR (1UL << 48)
|
||||
#endif
|
||||
#ifndef HWCAP2_LUT
|
||||
#define HWCAP2_LUT (1UL << 49)
|
||||
#endif
|
||||
#ifndef HWCAP2_FAMINMAX
|
||||
#define HWCAP2_FAMINMAX (1UL << 50)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8CVT
|
||||
#define HWCAP2_F8CVT (1UL << 51)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8FMA
|
||||
#define HWCAP2_F8FMA (1UL << 52)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8DP4
|
||||
#define HWCAP2_F8DP4 (1UL << 53)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8DP2
|
||||
#define HWCAP2_F8DP2 (1UL << 54)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8E4M3
|
||||
#define HWCAP2_F8E4M3 (1UL << 55)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8E5M2
|
||||
#define HWCAP2_F8E5M2 (1UL << 56)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_LUTV2
|
||||
#define HWCAP2_SME_LUTV2 (1UL << 57)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_F8F16
|
||||
#define HWCAP2_SME_F8F16 (1UL << 58)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_F8F32
|
||||
#define HWCAP2_SME_F8F32 (1UL << 59)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_SF8FMA
|
||||
#define HWCAP2_SME_SF8FMA (1UL << 60)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_SF8DP4
|
||||
#define HWCAP2_SME_SF8DP4 (1UL << 61)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME_SF8DP2
|
||||
#define HWCAP2_SME_SF8DP2 (1UL << 62)
|
||||
#endif
|
||||
#ifndef HWCAP2_POE
|
||||
#define HWCAP2_POE (1UL << 63)
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP3_MTE_FAR
|
||||
#define HWCAP3_MTE_FAR (1UL << 0)
|
||||
#endif
|
||||
#ifndef HWCAP3_MTE_STORE_ONLY
|
||||
#define HWCAP3_MTE_STORE_ONLY (1UL << 1)
|
||||
#endif
|
||||
#ifndef HWCAP3_LSFE
|
||||
#define HWCAP3_LSFE (1UL << 2)
|
||||
#endif
|
||||
#ifndef HWCAP3_LS64
|
||||
#define HWCAP3_LS64 (1UL << 3)
|
||||
#endif
|
||||
#ifndef HWCAP3_SVE_B16MM
|
||||
#define HWCAP3_SVE_B16MM (1UL << 4)
|
||||
#endif
|
||||
#ifndef HWCAP3_SVE2P3
|
||||
#define HWCAP3_SVE2P3 (1UL << 5)
|
||||
#endif
|
||||
#ifndef HWCAP3_SME_LUT6
|
||||
#define HWCAP3_SME_LUT6 (1UL << 6)
|
||||
#endif
|
||||
#ifndef HWCAP3_SME2P3
|
||||
#define HWCAP3_SME2P3 (1UL << 7)
|
||||
#endif
|
||||
#ifndef HWCAP3_F16MM
|
||||
#define HWCAP3_F16MM (1UL << 8)
|
||||
#endif
|
||||
#ifndef HWCAP3_F16F32DOT
|
||||
#define HWCAP3_F16F32DOT (1UL << 9)
|
||||
#endif
|
||||
#ifndef HWCAP3_F16F32MM
|
||||
#define HWCAP3_F16F32MM (1UL << 10)
|
||||
#endif
|
||||
#ifndef HWCAP3_SVE_LUT6
|
||||
#define HWCAP3_SVE_LUT6 (1UL << 11)
|
||||
#endif
|
||||
#endif
|
||||
+28
-7
@@ -516,21 +516,19 @@ static int condition_test_virtualization(Condition *c, char **env) {
|
||||
return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v));
|
||||
}
|
||||
|
||||
static int condition_test_architecture(Condition *c, char **env) {
|
||||
static int condition_test_architecture_parameter(const char *parameter) {
|
||||
Architecture a, b;
|
||||
|
||||
assert(c);
|
||||
assert(c->parameter);
|
||||
assert(c->type == CONDITION_ARCHITECTURE);
|
||||
assert(parameter);
|
||||
|
||||
a = uname_architecture();
|
||||
if (a < 0)
|
||||
return a;
|
||||
|
||||
if (streq(c->parameter, "native"))
|
||||
if (streq(parameter, "native"))
|
||||
b = native_architecture();
|
||||
else {
|
||||
b = architecture_from_string(c->parameter);
|
||||
b = architecture_from_string(parameter);
|
||||
if (b < 0) /* unknown architecture? Then it's definitely not ours */
|
||||
return false;
|
||||
}
|
||||
@@ -538,6 +536,14 @@ static int condition_test_architecture(Condition *c, char **env) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
static int condition_test_architecture(Condition *c, char **env) {
|
||||
assert(c);
|
||||
assert(c->parameter);
|
||||
assert(c->type == CONDITION_ARCHITECTURE);
|
||||
|
||||
return condition_test_architecture_parameter(c->parameter);
|
||||
}
|
||||
|
||||
#define DTCOMPAT_FILE "/proc/device-tree/compatible"
|
||||
static int condition_test_firmware_devicetree_compatible(const char *dtcarg) {
|
||||
int r;
|
||||
@@ -1080,11 +1086,26 @@ static int condition_test_path_is_read_write(Condition *c, char **env) {
|
||||
}
|
||||
|
||||
static int condition_test_cpufeature(Condition *c, char **env) {
|
||||
_cleanup_free_ char *cpu_arch = NULL, *feature = NULL;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(c->parameter);
|
||||
assert(c->type == CONDITION_CPU_FEATURE);
|
||||
|
||||
return has_cpu_with_flag(ascii_strlower(c->parameter));
|
||||
r = split_pair(c->parameter, ".", &cpu_arch, &feature);
|
||||
if (r >= 0) {
|
||||
r = condition_test_architecture_parameter(cpu_arch);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
} else if (r == -EINVAL) {
|
||||
feature = strdup(c->parameter);
|
||||
if (!feature)
|
||||
return -ENOMEM;
|
||||
} else
|
||||
return r;
|
||||
|
||||
return has_cpu_with_flag(ascii_strlower(feature));
|
||||
}
|
||||
|
||||
static int condition_test_path_is_encrypted(Condition *c, char **env) {
|
||||
|
||||
@@ -846,14 +846,52 @@ TEST(condition_test_credential) {
|
||||
ASSERT_OK(set_unset_env("ENCRYPTED_CREDENTIALS_DIRECTORY", d2, /* overwrite= */ true));
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
|
||||
TEST(condition_test_cpufeature) {
|
||||
Condition *condition;
|
||||
|
||||
#if defined(__i386__)
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "fpu", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "x86.fpu", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "bogus.fpu", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
#elif defined(__x86_64__)
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "fpu", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "x86-64.fpu", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "bogus.fpu", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
#elif defined(__aarch64__)
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "fp", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "asimd", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "arm64.asimd", false, false)));
|
||||
ASSERT_OK_POSITIVE(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "bogus.asimd", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
#endif
|
||||
|
||||
ASSERT_NOT_NULL((condition = condition_new(CONDITION_CPU_FEATURE, "somecpufeaturethatreallydoesntmakesense", false, false)));
|
||||
ASSERT_OK_ZERO(condition_test(condition, environ));
|
||||
condition_free(condition);
|
||||
|
||||
Reference in New Issue
Block a user