aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/processor.h22
-rw-r--r--arch/s390/include/asm/ptrace.h4
-rw-r--r--arch/s390/kernel/signal.c5
-rw-r--r--arch/s390/mm/fault.c2
4 files changed, 29 insertions, 4 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index a4b6229e5d4b..306c93c1b184 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -187,7 +187,6 @@ static inline void __load_psw(psw_t psw)
187 * Set PSW mask to specified value, while leaving the 187 * Set PSW mask to specified value, while leaving the
188 * PSW addr pointing to the next instruction. 188 * PSW addr pointing to the next instruction.
189 */ 189 */
190
191static inline void __load_psw_mask (unsigned long mask) 190static inline void __load_psw_mask (unsigned long mask)
192{ 191{
193 unsigned long addr; 192 unsigned long addr;
@@ -212,6 +211,27 @@ static inline void __load_psw_mask (unsigned long mask)
212 : "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc"); 211 : "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
213#endif /* __s390x__ */ 212#endif /* __s390x__ */
214} 213}
214
215/*
216 * Rewind PSW instruction address by specified number of bytes.
217 */
218static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
219{
220#ifndef __s390x__
221 if (psw.addr & PSW_ADDR_AMODE)
222 /* 31 bit mode */
223 return (psw.addr - ilc) | PSW_ADDR_AMODE;
224 /* 24 bit mode */
225 return (psw.addr - ilc) & ((1UL << 24) - 1);
226#else
227 unsigned long mask;
228
229 mask = (psw.mask & PSW_MASK_EA) ? -1UL :
230 (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 :
231 (1UL << 24) - 1;
232 return (psw.addr - ilc) & mask;
233#endif
234}
215 235
216/* 236/*
217 * Function to stop a processor until an interruption occurred 237 * Function to stop a processor until an interruption occurred
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 93c907b4776f..2904cc66967a 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -236,6 +236,8 @@ typedef struct
236#define PSW_MASK_ASC 0x0000C000UL 236#define PSW_MASK_ASC 0x0000C000UL
237#define PSW_MASK_CC 0x00003000UL 237#define PSW_MASK_CC 0x00003000UL
238#define PSW_MASK_PM 0x00000F00UL 238#define PSW_MASK_PM 0x00000F00UL
239#define PSW_MASK_EA 0x00000000UL
240#define PSW_MASK_BA 0x00000000UL
239 241
240#define PSW_ADDR_AMODE 0x80000000UL 242#define PSW_ADDR_AMODE 0x80000000UL
241#define PSW_ADDR_INSN 0x7FFFFFFFUL 243#define PSW_ADDR_INSN 0x7FFFFFFFUL
@@ -261,6 +263,8 @@ typedef struct
261#define PSW_MASK_ASC 0x0000C00000000000UL 263#define PSW_MASK_ASC 0x0000C00000000000UL
262#define PSW_MASK_CC 0x0000300000000000UL 264#define PSW_MASK_CC 0x0000300000000000UL
263#define PSW_MASK_PM 0x00000F0000000000UL 265#define PSW_MASK_PM 0x00000F0000000000UL
266#define PSW_MASK_EA 0x0000000100000000UL
267#define PSW_MASK_BA 0x0000000080000000UL
264 268
265#define PSW_ADDR_AMODE 0x0000000000000000UL 269#define PSW_ADDR_AMODE 0x0000000000000000UL
266#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL 270#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index e751cab80e04..058e372bada1 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -447,8 +447,9 @@ void do_signal(struct pt_regs *regs)
447 /* fallthrough */ 447 /* fallthrough */
448 case -ERESTARTNOINTR: 448 case -ERESTARTNOINTR:
449 regs->gprs[2] = regs->orig_gpr2; 449 regs->gprs[2] = regs->orig_gpr2;
450 regs->psw.addr = regs->psw.addr - 450 regs->psw.addr =
451 (regs->svc_code >> 16); 451 __rewind_psw(regs->psw,
452 regs->svc_code >> 16);
452 break; 453 break;
453 } 454 }
454 /* No longer in a system call */ 455 /* No longer in a system call */
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 9564fc779b27..a90fd91a9c72 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -393,7 +393,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code,
393 int fault; 393 int fault;
394 394
395 /* Protection exception is suppressing, decrement psw address. */ 395 /* Protection exception is suppressing, decrement psw address. */
396 regs->psw.addr -= (pgm_int_code >> 16); 396 regs->psw.addr = __rewind_psw(regs->psw, pgm_int_code >> 16);
397 /* 397 /*
398 * Check for low-address protection. This needs to be treated 398 * Check for low-address protection. This needs to be treated
399 * as a special case because the translation exception code 399 * as a special case because the translation exception code