Commit 9f930478 authored by Will Deacon's avatar Will Deacon

Merge branch 'for-next/cpufeature' into for-next/core

* for-next/cpufeature:
  kselftest/arm64: Add SVE 2.1 to hwcap test
  arm64/hwcap: Add support for SVE 2.1
  kselftest/arm64: Add FEAT_RPRFM to the hwcap test
  arm64/hwcap: Add support for FEAT_RPRFM
  kselftest/arm64: Add FEAT_CSSC to the hwcap selftest
  arm64/hwcap: Add support for FEAT_CSSC
  arm64: Enable data independent timing (DIT) in the kernel
parents d49d7c2e c5195b02
...@@ -275,6 +275,15 @@ HWCAP2_EBF16 ...@@ -275,6 +275,15 @@ HWCAP2_EBF16
HWCAP2_SVE_EBF16 HWCAP2_SVE_EBF16
Functionality implied by ID_AA64ZFR0_EL1.BF16 == 0b0010. Functionality implied by ID_AA64ZFR0_EL1.BF16 == 0b0010.
HWCAP2_CSSC
Functionality implied by ID_AA64ISAR2_EL1.CSSC == 0b0001.
HWCAP2_RPRFM
Functionality implied by ID_AA64ISAR2_EL1.RPRFM == 0b0001.
HWCAP2_SVE2P1
Functionality implied by ID_AA64ZFR0_EL1.SVEver == 0b0010.
4. Unused AT_HWCAP bits 4. Unused AT_HWCAP bits
----------------------- -----------------------
......
...@@ -52,6 +52,7 @@ model features for SVE is included in Appendix A. ...@@ -52,6 +52,7 @@ model features for SVE is included in Appendix A.
HWCAP2_SVEBITPERM HWCAP2_SVEBITPERM
HWCAP2_SVESHA3 HWCAP2_SVESHA3
HWCAP2_SVESM4 HWCAP2_SVESM4
HWCAP2_SVE2P1
This list may be extended over time as the SVE architecture evolves. This list may be extended over time as the SVE architecture evolves.
......
...@@ -120,6 +120,9 @@ ...@@ -120,6 +120,9 @@
#define KERNEL_HWCAP_WFXT __khwcap2_feature(WFXT) #define KERNEL_HWCAP_WFXT __khwcap2_feature(WFXT)
#define KERNEL_HWCAP_EBF16 __khwcap2_feature(EBF16) #define KERNEL_HWCAP_EBF16 __khwcap2_feature(EBF16)
#define KERNEL_HWCAP_SVE_EBF16 __khwcap2_feature(SVE_EBF16) #define KERNEL_HWCAP_SVE_EBF16 __khwcap2_feature(SVE_EBF16)
#define KERNEL_HWCAP_CSSC __khwcap2_feature(CSSC)
#define KERNEL_HWCAP_RPRFM __khwcap2_feature(RPRFM)
#define KERNEL_HWCAP_SVE2P1 __khwcap2_feature(SVE2P1)
/* /*
* This yields a mask that user programs can use to figure out what * This yields a mask that user programs can use to figure out what
......
...@@ -90,20 +90,24 @@ ...@@ -90,20 +90,24 @@
*/ */
#define pstate_field(op1, op2) ((op1) << Op1_shift | (op2) << Op2_shift) #define pstate_field(op1, op2) ((op1) << Op1_shift | (op2) << Op2_shift)
#define PSTATE_Imm_shift CRm_shift #define PSTATE_Imm_shift CRm_shift
#define SET_PSTATE(x, r) __emit_inst(0xd500401f | PSTATE_ ## r | ((!!x) << PSTATE_Imm_shift))
#define PSTATE_PAN pstate_field(0, 4) #define PSTATE_PAN pstate_field(0, 4)
#define PSTATE_UAO pstate_field(0, 3) #define PSTATE_UAO pstate_field(0, 3)
#define PSTATE_SSBS pstate_field(3, 1) #define PSTATE_SSBS pstate_field(3, 1)
#define PSTATE_DIT pstate_field(3, 2)
#define PSTATE_TCO pstate_field(3, 4) #define PSTATE_TCO pstate_field(3, 4)
#define SET_PSTATE_PAN(x) __emit_inst(0xd500401f | PSTATE_PAN | ((!!x) << PSTATE_Imm_shift)) #define SET_PSTATE_PAN(x) SET_PSTATE((x), PAN)
#define SET_PSTATE_UAO(x) __emit_inst(0xd500401f | PSTATE_UAO | ((!!x) << PSTATE_Imm_shift)) #define SET_PSTATE_UAO(x) SET_PSTATE((x), UAO)
#define SET_PSTATE_SSBS(x) __emit_inst(0xd500401f | PSTATE_SSBS | ((!!x) << PSTATE_Imm_shift)) #define SET_PSTATE_SSBS(x) SET_PSTATE((x), SSBS)
#define SET_PSTATE_TCO(x) __emit_inst(0xd500401f | PSTATE_TCO | ((!!x) << PSTATE_Imm_shift)) #define SET_PSTATE_DIT(x) SET_PSTATE((x), DIT)
#define SET_PSTATE_TCO(x) SET_PSTATE((x), TCO)
#define set_pstate_pan(x) asm volatile(SET_PSTATE_PAN(x)) #define set_pstate_pan(x) asm volatile(SET_PSTATE_PAN(x))
#define set_pstate_uao(x) asm volatile(SET_PSTATE_UAO(x)) #define set_pstate_uao(x) asm volatile(SET_PSTATE_UAO(x))
#define set_pstate_ssbs(x) asm volatile(SET_PSTATE_SSBS(x)) #define set_pstate_ssbs(x) asm volatile(SET_PSTATE_SSBS(x))
#define set_pstate_dit(x) asm volatile(SET_PSTATE_DIT(x))
#define __SYS_BARRIER_INSN(CRm, op2, Rt) \ #define __SYS_BARRIER_INSN(CRm, op2, Rt) \
__emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f)) __emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f))
......
...@@ -93,5 +93,8 @@ ...@@ -93,5 +93,8 @@
#define HWCAP2_WFXT (1UL << 31) #define HWCAP2_WFXT (1UL << 31)
#define HWCAP2_EBF16 (1UL << 32) #define HWCAP2_EBF16 (1UL << 32)
#define HWCAP2_SVE_EBF16 (1UL << 33) #define HWCAP2_SVE_EBF16 (1UL << 33)
#define HWCAP2_CSSC (1UL << 34)
#define HWCAP2_RPRFM (1UL << 35)
#define HWCAP2_SVE2P1 (1UL << 36)
#endif /* _UAPI__ASM_HWCAP_H */ #endif /* _UAPI__ASM_HWCAP_H */
...@@ -212,6 +212,8 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { ...@@ -212,6 +212,8 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
}; };
static const struct arm64_ftr_bits ftr_id_aa64isar2[] = { static const struct arm64_ftr_bits ftr_id_aa64isar2[] = {
ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH), ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
FTR_STRICT, FTR_EXACT, ID_AA64ISAR2_EL1_APA3_SHIFT, 4, 0), FTR_STRICT, FTR_EXACT, ID_AA64ISAR2_EL1_APA3_SHIFT, 4, 0),
...@@ -2101,6 +2103,11 @@ static void cpu_trap_el0_impdef(const struct arm64_cpu_capabilities *__unused) ...@@ -2101,6 +2103,11 @@ static void cpu_trap_el0_impdef(const struct arm64_cpu_capabilities *__unused)
sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_TIDCP); sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_TIDCP);
} }
static void cpu_enable_dit(const struct arm64_cpu_capabilities *__unused)
{
set_pstate_dit(1);
}
/* Internal helper functions to match cpu capability type */ /* Internal helper functions to match cpu capability type */
static bool static bool
cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap) cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap)
...@@ -2664,6 +2671,18 @@ static const struct arm64_cpu_capabilities arm64_features[] = { ...@@ -2664,6 +2671,18 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.matches = has_cpuid_feature, .matches = has_cpuid_feature,
.cpu_enable = cpu_trap_el0_impdef, .cpu_enable = cpu_trap_el0_impdef,
}, },
{
.desc = "Data independent timing control (DIT)",
.capability = ARM64_HAS_DIT,
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
.sys_reg = SYS_ID_AA64PFR0_EL1,
.sign = FTR_UNSIGNED,
.field_pos = ID_AA64PFR0_EL1_DIT_SHIFT,
.field_width = 4,
.min_field_value = ID_AA64PFR0_EL1_DIT_IMP,
.matches = has_cpuid_feature,
.cpu_enable = cpu_enable_dit,
},
{}, {},
}; };
...@@ -2772,6 +2791,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { ...@@ -2772,6 +2791,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_EL1_AT_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_USCAT), HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_EL1_AT_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_USCAT),
#ifdef CONFIG_ARM64_SVE #ifdef CONFIG_ARM64_SVE
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_EL1_SVE_SHIFT, 4, FTR_UNSIGNED, ID_AA64PFR0_EL1_SVE_IMP, CAP_HWCAP, KERNEL_HWCAP_SVE), HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_EL1_SVE_SHIFT, 4, FTR_UNSIGNED, ID_AA64PFR0_EL1_SVE_IMP, CAP_HWCAP, KERNEL_HWCAP_SVE),
HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_SVEver_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_SVEver_SVE2p1, CAP_HWCAP, KERNEL_HWCAP_SVE2P1),
HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_SVEver_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_SVEver_SVE2, CAP_HWCAP, KERNEL_HWCAP_SVE2), HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_SVEver_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_SVEver_SVE2, CAP_HWCAP, KERNEL_HWCAP_SVE2),
HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_AES_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_AES_IMP, CAP_HWCAP, KERNEL_HWCAP_SVEAES), HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_AES_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_AES_IMP, CAP_HWCAP, KERNEL_HWCAP_SVEAES),
HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_AES_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_AES_PMULL128, CAP_HWCAP, KERNEL_HWCAP_SVEPMULL), HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_AES_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_AES_PMULL128, CAP_HWCAP, KERNEL_HWCAP_SVEPMULL),
...@@ -2798,6 +2818,8 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { ...@@ -2798,6 +2818,8 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
#endif /* CONFIG_ARM64_MTE */ #endif /* CONFIG_ARM64_MTE */
HWCAP_CAP(SYS_ID_AA64MMFR0_EL1, ID_AA64MMFR0_EL1_ECV_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ECV), HWCAP_CAP(SYS_ID_AA64MMFR0_EL1, ID_AA64MMFR0_EL1_ECV_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ECV),
HWCAP_CAP(SYS_ID_AA64MMFR1_EL1, ID_AA64MMFR1_EL1_AFP_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_AFP), HWCAP_CAP(SYS_ID_AA64MMFR1_EL1, ID_AA64MMFR1_EL1_AFP_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_AFP),
HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, FTR_UNSIGNED, ID_AA64ISAR2_EL1_CSSC_IMP, CAP_HWCAP, KERNEL_HWCAP_CSSC),
HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, FTR_UNSIGNED, ID_AA64ISAR2_EL1_RPRFM_IMP, CAP_HWCAP, KERNEL_HWCAP_RPRFM),
HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_RPRES_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_RPRES), HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_RPRES_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_RPRES),
HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_WFxT_SHIFT, 4, FTR_UNSIGNED, ID_AA64ISAR2_EL1_WFxT_IMP, CAP_HWCAP, KERNEL_HWCAP_WFXT), HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_WFxT_SHIFT, 4, FTR_UNSIGNED, ID_AA64ISAR2_EL1_WFxT_IMP, CAP_HWCAP, KERNEL_HWCAP_WFXT),
#ifdef CONFIG_ARM64_SME #ifdef CONFIG_ARM64_SME
......
...@@ -116,6 +116,9 @@ static const char *const hwcap_str[] = { ...@@ -116,6 +116,9 @@ static const char *const hwcap_str[] = {
[KERNEL_HWCAP_WFXT] = "wfxt", [KERNEL_HWCAP_WFXT] = "wfxt",
[KERNEL_HWCAP_EBF16] = "ebf16", [KERNEL_HWCAP_EBF16] = "ebf16",
[KERNEL_HWCAP_SVE_EBF16] = "sveebf16", [KERNEL_HWCAP_SVE_EBF16] = "sveebf16",
[KERNEL_HWCAP_CSSC] = "cssc",
[KERNEL_HWCAP_RPRFM] = "rprfm",
[KERNEL_HWCAP_SVE2P1] = "sve2p1",
}; };
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
......
...@@ -197,6 +197,9 @@ alternative_cb_end ...@@ -197,6 +197,9 @@ alternative_cb_end
.endm .endm
.macro kernel_entry, el, regsize = 64 .macro kernel_entry, el, regsize = 64
.if \el == 0
alternative_insn nop, SET_PSTATE_DIT(1), ARM64_HAS_DIT
.endif
.if \regsize == 32 .if \regsize == 32
mov w0, w0 // zero upper 32 bits of x0 mov w0, w0 // zero upper 32 bits of x0
.endif .endif
......
...@@ -60,6 +60,8 @@ void notrace __cpu_suspend_exit(void) ...@@ -60,6 +60,8 @@ void notrace __cpu_suspend_exit(void)
* PSTATE was not saved over suspend/resume, re-enable any detected * PSTATE was not saved over suspend/resume, re-enable any detected
* features that might not have been set correctly. * features that might not have been set correctly.
*/ */
if (cpus_have_const_cap(ARM64_HAS_DIT))
set_pstate_dit(1);
__uaccess_enable_hw_pan(); __uaccess_enable_hw_pan();
/* /*
......
...@@ -20,6 +20,7 @@ HAS_CNP ...@@ -20,6 +20,7 @@ HAS_CNP
HAS_CRC32 HAS_CRC32
HAS_DCPODP HAS_DCPODP
HAS_DCPOP HAS_DCPOP
HAS_DIT
HAS_E0PD HAS_E0PD
HAS_ECV HAS_ECV
HAS_EPAN HAS_EPAN
......
...@@ -210,6 +210,7 @@ EndEnum ...@@ -210,6 +210,7 @@ EndEnum
Enum 3:0 SVEver Enum 3:0 SVEver
0b0000 IMP 0b0000 IMP
0b0001 SVE2 0b0001 SVE2
0b0010 SVE2p1
EndEnum EndEnum
EndSysreg EndSysreg
...@@ -484,7 +485,16 @@ EndEnum ...@@ -484,7 +485,16 @@ EndEnum
EndSysreg EndSysreg
Sysreg ID_AA64ISAR2_EL1 3 0 0 6 2 Sysreg ID_AA64ISAR2_EL1 3 0 0 6 2
Res0 63:28 Res0 63:56
Enum 55:52 CSSC
0b0000 NI
0b0001 IMP
EndEnum
Enum 51:48 RPRFM
0b0000 NI
0b0001 IMP
EndEnum
Res0 47:28
Enum 27:24 PAC_frac Enum 27:24 PAC_frac
0b0000 NI 0b0000 NI
0b0001 IMP 0b0001 IMP
......
...@@ -33,6 +33,12 @@ ...@@ -33,6 +33,12 @@
*/ */
typedef void (*sigill_fn)(void); typedef void (*sigill_fn)(void);
static void cssc_sigill(void)
{
/* CNT x0, x0 */
asm volatile(".inst 0xdac01c00" : : : "x0");
}
static void rng_sigill(void) static void rng_sigill(void)
{ {
asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0"); asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
...@@ -56,6 +62,12 @@ static void sve2_sigill(void) ...@@ -56,6 +62,12 @@ static void sve2_sigill(void)
asm volatile(".inst 0x4408A000" : : : "z0"); asm volatile(".inst 0x4408A000" : : : "z0");
} }
static void sve2p1_sigill(void)
{
/* BFADD Z0.H, Z0.H, Z0.H */
asm volatile(".inst 0x65000000" : : : "z0");
}
static void sveaes_sigill(void) static void sveaes_sigill(void)
{ {
/* AESD z0.b, z0.b, z0.b */ /* AESD z0.b, z0.b, z0.b */
...@@ -118,6 +130,13 @@ static const struct hwcap_data { ...@@ -118,6 +130,13 @@ static const struct hwcap_data {
sigill_fn sigill_fn; sigill_fn sigill_fn;
bool sigill_reliable; bool sigill_reliable;
} hwcaps[] = { } hwcaps[] = {
{
.name = "CSSC",
.at_hwcap = AT_HWCAP2,
.hwcap_bit = HWCAP2_CSSC,
.cpuinfo = "cssc",
.sigill_fn = cssc_sigill,
},
{ {
.name = "RNG", .name = "RNG",
.at_hwcap = AT_HWCAP2, .at_hwcap = AT_HWCAP2,
...@@ -125,6 +144,12 @@ static const struct hwcap_data { ...@@ -125,6 +144,12 @@ static const struct hwcap_data {
.cpuinfo = "rng", .cpuinfo = "rng",
.sigill_fn = rng_sigill, .sigill_fn = rng_sigill,
}, },
{
.name = "RPRFM",
.at_hwcap = AT_HWCAP2,
.hwcap_bit = HWCAP2_RPRFM,
.cpuinfo = "rprfm",
},
{ {
.name = "SME", .name = "SME",
.at_hwcap = AT_HWCAP2, .at_hwcap = AT_HWCAP2,
...@@ -148,6 +173,13 @@ static const struct hwcap_data { ...@@ -148,6 +173,13 @@ static const struct hwcap_data {
.cpuinfo = "sve2", .cpuinfo = "sve2",
.sigill_fn = sve2_sigill, .sigill_fn = sve2_sigill,
}, },
{
.name = "SVE 2.1",
.at_hwcap = AT_HWCAP2,
.hwcap_bit = HWCAP2_SVE2P1,
.cpuinfo = "sve2p1",
.sigill_fn = sve2p1_sigill,
},
{ {
.name = "SVE AES", .name = "SVE AES",
.at_hwcap = AT_HWCAP2, .at_hwcap = AT_HWCAP2,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment