git: 205c1007be6d - main - arm64: Enable SVE in userspace
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 30 Sep 2024 12:23:41 UTC
The branch main has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=205c1007be6d57b2eb8620f79384cb2299dde40e
commit 205c1007be6d57b2eb8620f79384cb2299dde40e
Author: Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2024-09-27 14:06:03 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2024-09-30 12:04:23 +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
---
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 eead0051d315..3bf4f9a80c90 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -1383,13 +1383,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, ""),
@@ -1463,7 +1460,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,
@@ -1578,59 +1576,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 35defef90837..fa0b46111a34 100644
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -639,8 +639,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 667353831f48..08a046762a58 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -1583,6 +1583,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