s390/gs: add regset for the guarded storage broadcast control block
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 20 Apr 2017 11:54:11 +0000 (13:54 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 21 Apr 2017 10:38:56 +0000 (12:38 +0200)
The guarded storage interface allows to register a control block for
each thread that is activated with the guarded storage broadcast event.
To retrieve the complete state of a process from the kernel a register
set for the stored broadcast control block is required.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/ptrace.c
include/uapi/linux/elf.h

index c933e255b5d577009b8d2abcf753a400cbb727b2..488c5bb8dc77db162332a9c2351fd6ddc7b0dd2a 100644 (file)
@@ -1171,10 +1171,48 @@ static int s390_gs_cb_set(struct task_struct *target,
 {
        struct gs_cb *data = target->thread.gs_cb;
 
+       if (!MACHINE_HAS_GS)
+               return -ENODEV;
+       if (!data) {
+               data = kzalloc(sizeof(*data), GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+               target->thread.gs_cb = data;
+       }
+       return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                 data, 0, sizeof(struct gs_cb));
+}
+
+static int s390_gs_bc_get(struct task_struct *target,
+                         const struct user_regset *regset,
+                         unsigned int pos, unsigned int count,
+                         void *kbuf, void __user *ubuf)
+{
+       struct gs_cb *data = target->thread.gs_bc_cb;
+
        if (!MACHINE_HAS_GS)
                return -ENODEV;
        if (!data)
                return -ENODATA;
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                  data, 0, sizeof(struct gs_cb));
+}
+
+static int s390_gs_bc_set(struct task_struct *target,
+                         const struct user_regset *regset,
+                         unsigned int pos, unsigned int count,
+                         const void *kbuf, const void __user *ubuf)
+{
+       struct gs_cb *data = target->thread.gs_bc_cb;
+
+       if (!MACHINE_HAS_GS)
+               return -ENODEV;
+       if (!data) {
+               data = kzalloc(sizeof(*data), GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+               target->thread.gs_bc_cb = data;
+       }
        return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                  data, 0, sizeof(struct gs_cb));
 }
@@ -1244,6 +1282,14 @@ static const struct user_regset s390_regsets[] = {
                .get = s390_gs_cb_get,
                .set = s390_gs_cb_set,
        },
+       {
+               .core_note_type = NT_S390_GS_BC,
+               .n = sizeof(struct gs_cb) / sizeof(__u64),
+               .size = sizeof(__u64),
+               .align = sizeof(__u64),
+               .get = s390_gs_bc_get,
+               .set = s390_gs_bc_set,
+       },
 };
 
 static const struct user_regset_view user_s390_view = {
index 8c6d3bdb9a00c5f7c7c4404e79ca35c8240e6e71..176b6cb1008dcd53615defd63d3930963107c2d0 100644 (file)
@@ -410,6 +410,7 @@ typedef struct elf64_shdr {
 #define NT_S390_VXRS_LOW       0x309   /* s390 vector registers 0-15 upper half */
 #define NT_S390_VXRS_HIGH      0x30a   /* s390 vector registers 16-31 */
 #define NT_S390_GS_CB  0x30b           /* s390 guarded storage registers */
+#define NT_S390_GS_BC  0x30c           /* s390 guarded storage broadcast control block */
 #define NT_ARM_VFP     0x400           /* ARM VFP/NEON registers */
 #define NT_ARM_TLS     0x401           /* ARM TLS register */
 #define NT_ARM_HW_BREAK        0x402           /* ARM hardware breakpoint registers */