|
@@ -42,6 +42,7 @@ enum s390_regset {
|
|
|
REGSET_GENERAL,
|
|
|
REGSET_FP,
|
|
|
REGSET_LAST_BREAK,
|
|
|
+ REGSET_TDB,
|
|
|
REGSET_SYSTEM_CALL,
|
|
|
REGSET_GENERAL_EXTENDED,
|
|
|
};
|
|
@@ -52,6 +53,21 @@ void update_per_regs(struct task_struct *task)
|
|
|
struct thread_struct *thread = &task->thread;
|
|
|
struct per_regs old, new;
|
|
|
|
|
|
+ /* Take care of the enable/disable of transactional execution. */
|
|
|
+ if (MACHINE_HAS_TE) {
|
|
|
+ unsigned long cr0, cr0_new;
|
|
|
+
|
|
|
+ __ctl_store(cr0, 0, 0);
|
|
|
+ /* set or clear transaction execution bits 8 and 9. */
|
|
|
+ if (task->thread.per_flags & PER_FLAG_NO_TE)
|
|
|
+ cr0_new = cr0 & ~(3UL << 54);
|
|
|
+ else
|
|
|
+ cr0_new = cr0 | (3UL << 54);
|
|
|
+ /* Only load control register 0 if necessary. */
|
|
|
+ if (cr0 != cr0_new)
|
|
|
+ __ctl_load(cr0_new, 0, 0);
|
|
|
+ }
|
|
|
+
|
|
|
/* Copy user specified PER registers */
|
|
|
new.control = thread->per_user.control;
|
|
|
new.start = thread->per_user.start;
|
|
@@ -60,6 +76,10 @@ void update_per_regs(struct task_struct *task)
|
|
|
/* merge TIF_SINGLE_STEP into user specified PER registers. */
|
|
|
if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
|
|
|
new.control |= PER_EVENT_IFETCH;
|
|
|
+#ifdef CONFIG_64BIT
|
|
|
+ new.control |= PER_CONTROL_SUSPENSION;
|
|
|
+ new.control |= PER_EVENT_TRANSACTION_END;
|
|
|
+#endif
|
|
|
new.start = 0;
|
|
|
new.end = PSW_ADDR_INSN;
|
|
|
}
|
|
@@ -100,6 +120,7 @@ void ptrace_disable(struct task_struct *task)
|
|
|
memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));
|
|
|
clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
|
|
|
clear_tsk_thread_flag(task, TIF_PER_TRAP);
|
|
|
+ task->thread.per_flags = 0;
|
|
|
}
|
|
|
|
|
|
#ifndef CONFIG_64BIT
|
|
@@ -416,6 +437,16 @@ long arch_ptrace(struct task_struct *child, long request,
|
|
|
put_user(task_thread_info(child)->last_break,
|
|
|
(unsigned long __user *) data);
|
|
|
return 0;
|
|
|
+ case PTRACE_ENABLE_TE:
|
|
|
+ if (!MACHINE_HAS_TE)
|
|
|
+ return -EIO;
|
|
|
+ child->thread.per_flags &= ~PER_FLAG_NO_TE;
|
|
|
+ return 0;
|
|
|
+ case PTRACE_DISABLE_TE:
|
|
|
+ if (!MACHINE_HAS_TE)
|
|
|
+ return -EIO;
|
|
|
+ child->thread.per_flags |= PER_FLAG_NO_TE;
|
|
|
+ return 0;
|
|
|
default:
|
|
|
/* Removing high order bit from addr (only for 31 bit). */
|
|
|
addr &= PSW_ADDR_INSN;
|
|
@@ -903,6 +934,28 @@ static int s390_last_break_set(struct task_struct *target,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int s390_tdb_get(struct task_struct *target,
|
|
|
+ const struct user_regset *regset,
|
|
|
+ unsigned int pos, unsigned int count,
|
|
|
+ void *kbuf, void __user *ubuf)
|
|
|
+{
|
|
|
+ struct pt_regs *regs = task_pt_regs(target);
|
|
|
+ unsigned char *data;
|
|
|
+
|
|
|
+ if (!(regs->int_code & 0x200))
|
|
|
+ return -ENODATA;
|
|
|
+ data = target->thread.trap_tdb;
|
|
|
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, data, 0, 256);
|
|
|
+}
|
|
|
+
|
|
|
+static int s390_tdb_set(struct task_struct *target,
|
|
|
+ const struct user_regset *regset,
|
|
|
+ unsigned int pos, unsigned int count,
|
|
|
+ const void *kbuf, const void __user *ubuf)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
#endif
|
|
|
|
|
|
static int s390_system_call_get(struct task_struct *target,
|
|
@@ -951,6 +1004,14 @@ static const struct user_regset s390_regsets[] = {
|
|
|
.get = s390_last_break_get,
|
|
|
.set = s390_last_break_set,
|
|
|
},
|
|
|
+ [REGSET_TDB] = {
|
|
|
+ .core_note_type = NT_S390_TDB,
|
|
|
+ .n = 1,
|
|
|
+ .size = 256,
|
|
|
+ .align = 1,
|
|
|
+ .get = s390_tdb_get,
|
|
|
+ .set = s390_tdb_set,
|
|
|
+ },
|
|
|
#endif
|
|
|
[REGSET_SYSTEM_CALL] = {
|
|
|
.core_note_type = NT_S390_SYSTEM_CALL,
|
|
@@ -1148,6 +1209,14 @@ static const struct user_regset s390_compat_regsets[] = {
|
|
|
.get = s390_compat_last_break_get,
|
|
|
.set = s390_compat_last_break_set,
|
|
|
},
|
|
|
+ [REGSET_TDB] = {
|
|
|
+ .core_note_type = NT_S390_TDB,
|
|
|
+ .n = 1,
|
|
|
+ .size = 256,
|
|
|
+ .align = 1,
|
|
|
+ .get = s390_tdb_get,
|
|
|
+ .set = s390_tdb_set,
|
|
|
+ },
|
|
|
[REGSET_SYSTEM_CALL] = {
|
|
|
.core_note_type = NT_S390_SYSTEM_CALL,
|
|
|
.n = 1,
|