diff options
Diffstat (limited to 'arch/s390/kernel/ptrace.c')
-rw-r--r-- | arch/s390/kernel/ptrace.c | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index ef86ad24398..5804cfa7cba 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -47,29 +47,31 @@ enum s390_regset { | |||
47 | 47 | ||
48 | void update_per_regs(struct task_struct *task) | 48 | void update_per_regs(struct task_struct *task) |
49 | { | 49 | { |
50 | static const struct per_regs per_single_step = { | ||
51 | .control = PER_EVENT_IFETCH, | ||
52 | .start = 0, | ||
53 | .end = PSW_ADDR_INSN, | ||
54 | }; | ||
55 | struct pt_regs *regs = task_pt_regs(task); | 50 | struct pt_regs *regs = task_pt_regs(task); |
56 | struct thread_struct *thread = &task->thread; | 51 | struct thread_struct *thread = &task->thread; |
57 | const struct per_regs *new; | 52 | struct per_regs old, new; |
58 | struct per_regs old; | 53 | |
59 | 54 | /* Copy user specified PER registers */ | |
60 | /* TIF_SINGLE_STEP overrides the user specified PER registers. */ | 55 | new.control = thread->per_user.control; |
61 | new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ? | 56 | new.start = thread->per_user.start; |
62 | &per_single_step : &thread->per_user; | 57 | new.end = thread->per_user.end; |
58 | |||
59 | /* merge TIF_SINGLE_STEP into user specified PER registers. */ | ||
60 | if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) { | ||
61 | new.control |= PER_EVENT_IFETCH; | ||
62 | new.start = 0; | ||
63 | new.end = PSW_ADDR_INSN; | ||
64 | } | ||
63 | 65 | ||
64 | /* Take care of the PER enablement bit in the PSW. */ | 66 | /* Take care of the PER enablement bit in the PSW. */ |
65 | if (!(new->control & PER_EVENT_MASK)) { | 67 | if (!(new.control & PER_EVENT_MASK)) { |
66 | regs->psw.mask &= ~PSW_MASK_PER; | 68 | regs->psw.mask &= ~PSW_MASK_PER; |
67 | return; | 69 | return; |
68 | } | 70 | } |
69 | regs->psw.mask |= PSW_MASK_PER; | 71 | regs->psw.mask |= PSW_MASK_PER; |
70 | __ctl_store(old, 9, 11); | 72 | __ctl_store(old, 9, 11); |
71 | if (memcmp(new, &old, sizeof(struct per_regs)) != 0) | 73 | if (memcmp(&new, &old, sizeof(struct per_regs)) != 0) |
72 | __ctl_load(*new, 9, 11); | 74 | __ctl_load(new, 9, 11); |
73 | } | 75 | } |
74 | 76 | ||
75 | void user_enable_single_step(struct task_struct *task) | 77 | void user_enable_single_step(struct task_struct *task) |
@@ -895,6 +897,14 @@ static int s390_last_break_get(struct task_struct *target, | |||
895 | return 0; | 897 | return 0; |
896 | } | 898 | } |
897 | 899 | ||
900 | static int s390_last_break_set(struct task_struct *target, | ||
901 | const struct user_regset *regset, | ||
902 | unsigned int pos, unsigned int count, | ||
903 | const void *kbuf, const void __user *ubuf) | ||
904 | { | ||
905 | return 0; | ||
906 | } | ||
907 | |||
898 | #endif | 908 | #endif |
899 | 909 | ||
900 | static const struct user_regset s390_regsets[] = { | 910 | static const struct user_regset s390_regsets[] = { |
@@ -921,6 +931,7 @@ static const struct user_regset s390_regsets[] = { | |||
921 | .size = sizeof(long), | 931 | .size = sizeof(long), |
922 | .align = sizeof(long), | 932 | .align = sizeof(long), |
923 | .get = s390_last_break_get, | 933 | .get = s390_last_break_get, |
934 | .set = s390_last_break_set, | ||
924 | }, | 935 | }, |
925 | #endif | 936 | #endif |
926 | }; | 937 | }; |
@@ -1078,6 +1089,14 @@ static int s390_compat_last_break_get(struct task_struct *target, | |||
1078 | return 0; | 1089 | return 0; |
1079 | } | 1090 | } |
1080 | 1091 | ||
1092 | static int s390_compat_last_break_set(struct task_struct *target, | ||
1093 | const struct user_regset *regset, | ||
1094 | unsigned int pos, unsigned int count, | ||
1095 | const void *kbuf, const void __user *ubuf) | ||
1096 | { | ||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1081 | static const struct user_regset s390_compat_regsets[] = { | 1100 | static const struct user_regset s390_compat_regsets[] = { |
1082 | [REGSET_GENERAL] = { | 1101 | [REGSET_GENERAL] = { |
1083 | .core_note_type = NT_PRSTATUS, | 1102 | .core_note_type = NT_PRSTATUS, |
@@ -1101,6 +1120,7 @@ static const struct user_regset s390_compat_regsets[] = { | |||
1101 | .size = sizeof(long), | 1120 | .size = sizeof(long), |
1102 | .align = sizeof(long), | 1121 | .align = sizeof(long), |
1103 | .get = s390_compat_last_break_get, | 1122 | .get = s390_compat_last_break_get, |
1123 | .set = s390_compat_last_break_set, | ||
1104 | }, | 1124 | }, |
1105 | [REGSET_GENERAL_EXTENDED] = { | 1125 | [REGSET_GENERAL_EXTENDED] = { |
1106 | .core_note_type = NT_S390_HIGH_GPRS, | 1126 | .core_note_type = NT_S390_HIGH_GPRS, |