]> Git Repo - linux.git/blobdiff - arch/arm64/kernel/ptrace.c
Merge branches 'for-next/gcs', 'for-next/probes', 'for-next/asm-offsets', 'for-next...
[linux.git] / arch / arm64 / kernel / ptrace.c
index b756578aeaeea1d3250276734520e3eaae8a671d..e4437f62a2cda93734052c44b48886db83d75b3e 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/cpufeature.h>
 #include <asm/debug-monitors.h>
 #include <asm/fpsimd.h>
+#include <asm/gcs.h>
 #include <asm/mte.h>
 #include <asm/pointer_auth.h>
 #include <asm/stacktrace.h>
@@ -898,7 +899,11 @@ static int sve_set_common(struct task_struct *target,
        if (ret)
                goto out;
 
-       /* Actual VL set may be less than the user asked for: */
+       /*
+        * Actual VL set may be different from what the user asked
+        * for, or we may have configured the _ONEXEC VL not the
+        * current VL:
+        */
        vq = sve_vq_from_vl(task_get_vl(target, type));
 
        /* Enter/exit streaming mode */
@@ -1125,7 +1130,11 @@ static int za_set(struct task_struct *target,
        if (ret)
                goto out;
 
-       /* Actual VL set may be less than the user asked for: */
+       /*
+        * Actual VL set may be different from what the user asked
+        * for, or we may have configured the _ONEXEC rather than
+        * current VL:
+        */
        vq = sve_vq_from_vl(task_get_sme_vl(target));
 
        /* Ensure there is some SVE storage for streaming mode */
@@ -1473,6 +1482,52 @@ static int poe_set(struct task_struct *target, const struct
 }
 #endif
 
+#ifdef CONFIG_ARM64_GCS
+static int gcs_get(struct task_struct *target,
+                  const struct user_regset *regset,
+                  struct membuf to)
+{
+       struct user_gcs user_gcs;
+
+       if (!system_supports_gcs())
+               return -EINVAL;
+
+       if (target == current)
+               gcs_preserve_current_state();
+
+       user_gcs.features_enabled = target->thread.gcs_el0_mode;
+       user_gcs.features_locked = target->thread.gcs_el0_locked;
+       user_gcs.gcspr_el0 = target->thread.gcspr_el0;
+
+       return membuf_write(&to, &user_gcs, sizeof(user_gcs));
+}
+
+static int gcs_set(struct task_struct *target, const struct
+                  user_regset *regset, unsigned int pos,
+                  unsigned int count, const void *kbuf, const
+                  void __user *ubuf)
+{
+       int ret;
+       struct user_gcs user_gcs;
+
+       if (!system_supports_gcs())
+               return -EINVAL;
+
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &user_gcs, 0, -1);
+       if (ret)
+               return ret;
+
+       if (user_gcs.features_enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK)
+               return -EINVAL;
+
+       target->thread.gcs_el0_mode = user_gcs.features_enabled;
+       target->thread.gcs_el0_locked = user_gcs.features_locked;
+       target->thread.gcspr_el0 = user_gcs.gcspr_el0;
+
+       return 0;
+}
+#endif
+
 enum aarch64_regset {
        REGSET_GPR,
        REGSET_FPR,
@@ -1503,7 +1558,10 @@ enum aarch64_regset {
        REGSET_TAGGED_ADDR_CTRL,
 #endif
 #ifdef CONFIG_ARM64_POE
-       REGSET_POE
+       REGSET_POE,
+#endif
+#ifdef CONFIG_ARM64_GCS
+       REGSET_GCS,
 #endif
 };
 
@@ -1674,6 +1732,16 @@ static const struct user_regset aarch64_regsets[] = {
                .set = poe_set,
        },
 #endif
+#ifdef CONFIG_ARM64_GCS
+       [REGSET_GCS] = {
+               .core_note_type = NT_ARM_GCS,
+               .n = sizeof(struct user_gcs) / sizeof(u64),
+               .size = sizeof(u64),
+               .align = sizeof(u64),
+               .regset_get = gcs_get,
+               .set = gcs_set,
+       },
+#endif
 };
 
 static const struct user_regset_view user_aarch64_view = {
This page took 0.032448 seconds and 4 git commands to generate.