git: 1f9635e2c213 - stable/14 - arm64: Enable SVE in userspace
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 21 Oct 2024 15:05:15 UTC
The branch stable/14 has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=1f9635e2c213368cfed3737970f3814fbb55a922
commit 1f9635e2c213368cfed3737970f3814fbb55a922
Author: Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2024-09-27 14:06:03 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2024-10-21 15:03:27 +0000
arm64: Enable SVE in userspace
Report when SVE is present and allow it to be used by calling
sve_restore_state on an SVE exception from userspace.
Reviewed by: kib
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D43310
(cherry picked from commit 205c1007be6d57b2eb8620f79384cb2299dde40e)
---
sys/arm64/arm64/identcpu.c | 82 ++++++++++++++++++++++++++++++++++++++--------
sys/arm64/arm64/trap.c | 6 ++--
sys/arm64/include/armreg.h | 1 +
3 files changed, 74 insertions(+), 15 deletions(-)
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index 84ad2d0eb282..22978af219dc 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -1384,13 +1384,10 @@ static const struct mrs_field_value id_aa64pfr0_sve[] = {
MRS_FIELD_VALUE_END,
};
-#if 0
-/* Enable when we add SVE support */
static const struct mrs_field_hwcap id_aa64pfr0_sve_caps[] = {
MRS_HWCAP(1, HWCAP_SVE, ID_AA64PFR0_SVE_IMPL),
MRS_HWCAP_END
};
-#endif
static const struct mrs_field_value id_aa64pfr0_ras[] = {
MRS_FIELD_VALUE(ID_AA64PFR0_RAS_NONE, ""),
@@ -1464,7 +1461,8 @@ static const struct mrs_field id_aa64pfr0_fields[] = {
MRS_FIELD(ID_AA64PFR0, AMU, false, MRS_EXACT, id_aa64pfr0_amu),
MRS_FIELD(ID_AA64PFR0, MPAM, false, MRS_EXACT, id_aa64pfr0_mpam),
MRS_FIELD(ID_AA64PFR0, SEL2, false, MRS_EXACT, id_aa64pfr0_sel2),
- MRS_FIELD(ID_AA64PFR0, SVE, false, MRS_EXACT, id_aa64pfr0_sve),
+ MRS_FIELD_HWCAP_SPLIT(ID_AA64PFR0, SVE, false, MRS_LOWER, MRS_EXACT,
+ id_aa64pfr0_sve, id_aa64pfr0_sve_caps),
MRS_FIELD(ID_AA64PFR0, RAS, false, MRS_EXACT, id_aa64pfr0_ras),
MRS_FIELD(ID_AA64PFR0, GIC, false, MRS_EXACT, id_aa64pfr0_gic),
MRS_FIELD_HWCAP(ID_AA64PFR0, AdvSIMD, true, MRS_LOWER,
@@ -1581,59 +1579,117 @@ static const struct mrs_field_value id_aa64zfr0_f64mm[] = {
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_f64mm_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVEF64MM, ID_AA64ZFR0_F64MM_IMPL),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field_value id_aa64zfr0_f32mm[] = {
MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, F32MM, NONE, IMPL),
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_f32mm_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVEF32MM, ID_AA64ZFR0_F32MM_IMPL),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field_value id_aa64zfr0_i8mm[] = {
MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, I8MM, NONE, IMPL),
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_i8mm_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVEI8MM, ID_AA64ZFR0_I8MM_IMPL),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field_value id_aa64zfr0_sm4[] = {
MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, SM4, NONE, IMPL),
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_sm4_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVESM4, ID_AA64ZFR0_SM4_IMPL),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field_value id_aa64zfr0_sha3[] = {
MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, SHA3, NONE, IMPL),
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_sha3_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVESHA3, ID_AA64ZFR0_SHA3_IMPL),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field_value id_aa64zfr0_bf16[] = {
MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, BF16, NONE, BASE),
MRS_FIELD_VALUE(ID_AA64ZFR0_BF16_EBF, "BF16+EBF"),
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_bf16_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVEBF16, ID_AA64ZFR0_BF16_BASE),
+ MRS_HWCAP(2, HWCAP2_SVE_EBF16, ID_AA64ZFR0_BF16_EBF),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field_value id_aa64zfr0_bitperm[] = {
MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, BitPerm, NONE, IMPL),
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_bitperm_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVEBITPERM, ID_AA64ZFR0_BitPerm_IMPL),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field_value id_aa64zfr0_aes[] = {
MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, AES, NONE, BASE),
MRS_FIELD_VALUE(ID_AA64ZFR0_AES_PMULL, "AES+PMULL"),
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_aes_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVEAES, ID_AA64ZFR0_AES_BASE),
+ MRS_HWCAP(2, HWCAP2_SVEPMULL, ID_AA64ZFR0_AES_PMULL),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field_value id_aa64zfr0_svever[] = {
MRS_FIELD_VALUE(ID_AA64ZFR0_SVEver_SVE1, "SVE1"),
MRS_FIELD_VALUE(ID_AA64ZFR0_SVEver_SVE2, "SVE2"),
+ MRS_FIELD_VALUE(ID_AA64ZFR0_SVEver_SVE2P1, "SVE2P1"),
MRS_FIELD_VALUE_END,
};
+static const struct mrs_field_hwcap id_aa64zfr0_svever_caps[] = {
+ MRS_HWCAP(2, HWCAP2_SVE2, ID_AA64ZFR0_SVEver_SVE2),
+ MRS_HWCAP(2, HWCAP2_SVE2P1, ID_AA64ZFR0_SVEver_SVE2P1),
+ MRS_HWCAP_END,
+};
+
static const struct mrs_field id_aa64zfr0_fields[] = {
- MRS_FIELD(ID_AA64ZFR0, F64MM, false, MRS_EXACT, id_aa64zfr0_f64mm),
- MRS_FIELD(ID_AA64ZFR0, F32MM, false, MRS_EXACT, id_aa64zfr0_f32mm),
- MRS_FIELD(ID_AA64ZFR0, I8MM, false, MRS_EXACT, id_aa64zfr0_i8mm),
- MRS_FIELD(ID_AA64ZFR0, SM4, false, MRS_EXACT, id_aa64zfr0_sm4),
- MRS_FIELD(ID_AA64ZFR0, SHA3, false, MRS_EXACT, id_aa64zfr0_sha3),
- MRS_FIELD(ID_AA64ZFR0, BF16, false, MRS_EXACT, id_aa64zfr0_bf16),
- MRS_FIELD(ID_AA64ZFR0, BitPerm, false, MRS_EXACT, id_aa64zfr0_bitperm),
- MRS_FIELD(ID_AA64ZFR0, AES, false, MRS_EXACT, id_aa64zfr0_aes),
- MRS_FIELD(ID_AA64ZFR0, SVEver, false, MRS_EXACT, id_aa64zfr0_svever),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, F64MM, false, MRS_LOWER,
+ id_aa64zfr0_f64mm, id_aa64zfr0_f64mm_caps),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, F32MM, false, MRS_LOWER,
+ id_aa64zfr0_f32mm, id_aa64zfr0_f32mm_caps),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, I8MM, false, MRS_LOWER, id_aa64zfr0_i8mm,
+ id_aa64zfr0_i8mm_caps),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, SM4, false, MRS_LOWER, id_aa64zfr0_sm4,
+ id_aa64zfr0_sm4_caps),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, SHA3, false, MRS_LOWER, id_aa64zfr0_sha3,
+ id_aa64zfr0_sha3_caps),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, BF16, false, MRS_LOWER, id_aa64zfr0_bf16,
+ id_aa64zfr0_bf16_caps),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, BitPerm, false, MRS_LOWER,
+ id_aa64zfr0_bitperm, id_aa64zfr0_bitperm_caps),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, AES, false, MRS_LOWER, id_aa64zfr0_aes,
+ id_aa64zfr0_aes_caps),
+ MRS_FIELD_HWCAP(ID_AA64ZFR0, SVEver, false, MRS_LOWER,
+ id_aa64zfr0_svever, id_aa64zfr0_svever_caps),
MRS_FIELD_END,
};
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
index 78582f5ac563..64a27b138a9a 100644
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -635,8 +635,10 @@ do_el0_sync(struct thread *td, struct trapframe *frame)
#endif
break;
case EXCP_SVE:
- call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_elr,
- exception);
+ /* Returns true if this thread can use SVE */
+ if (!sve_restore_state(td))
+ call_trapsignal(td, SIGILL, ILL_ILLTRP,
+ (void *)frame->tf_elr, exception);
userret(td, frame);
break;
case EXCP_SVC32:
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
index 2b92c036ef1c..6a3db5adc930 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -1535,6 +1535,7 @@
#define ID_AA64ZFR0_SVEver_VAL(x) ((x) & ID_AA64ZFR0_SVEver_MASK
#define ID_AA64ZFR0_SVEver_SVE1 (UL(0x0) << ID_AA64ZFR0_SVEver_SHIFT)
#define ID_AA64ZFR0_SVEver_SVE2 (UL(0x1) << ID_AA64ZFR0_SVEver_SHIFT)
+#define ID_AA64ZFR0_SVEver_SVE2P1 (UL(0x2) << ID_AA64ZFR0_SVEver_SHIFT)
#define ID_AA64ZFR0_AES_SHIFT 4
#define ID_AA64ZFR0_AES_MASK (UL(0xf) << ID_AA64ZFR0_AES_SHIFT)
#define ID_AA64ZFR0_AES_VAL(x) ((x) & ID_AA64ZFR0_AES_MASK