|
@@ -37,6 +37,7 @@
|
|
#include <linux/sched/task_stack.h>
|
|
#include <linux/sched/task_stack.h>
|
|
#include <linux/signal.h>
|
|
#include <linux/signal.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/slab.h>
|
|
|
|
+#include <linux/stddef.h>
|
|
#include <linux/sysctl.h>
|
|
#include <linux/sysctl.h>
|
|
|
|
|
|
#include <asm/esr.h>
|
|
#include <asm/esr.h>
|
|
@@ -755,6 +756,33 @@ void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
|
|
isb();
|
|
isb();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Read the pseudo-ZCR used by cpufeatures to identify the supported SVE
|
|
|
|
+ * vector length.
|
|
|
|
+ *
|
|
|
|
+ * Use only if SVE is present.
|
|
|
|
+ * This function clobbers the SVE vector length.
|
|
|
|
+ */
|
|
|
|
+u64 read_zcr_features(void)
|
|
|
|
+{
|
|
|
|
+ u64 zcr;
|
|
|
|
+ unsigned int vq_max;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Set the maximum possible VL, and write zeroes to all other
|
|
|
|
+ * bits to see if they stick.
|
|
|
|
+ */
|
|
|
|
+ sve_kernel_enable(NULL);
|
|
|
|
+ write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL1);
|
|
|
|
+
|
|
|
|
+ zcr = read_sysreg_s(SYS_ZCR_EL1);
|
|
|
|
+ zcr &= ~(u64)ZCR_ELx_LEN_MASK; /* find sticky 1s outside LEN field */
|
|
|
|
+ vq_max = sve_vq_from_vl(sve_get_vl());
|
|
|
|
+ zcr |= vq_max - 1; /* set LEN field to maximum effective value */
|
|
|
|
+
|
|
|
|
+ return zcr;
|
|
|
|
+}
|
|
|
|
+
|
|
void __init sve_setup(void)
|
|
void __init sve_setup(void)
|
|
{
|
|
{
|
|
u64 zcr;
|
|
u64 zcr;
|