diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/include/asm/processor.h | 22 | ||||
-rw-r--r-- | arch/s390/include/asm/ptrace.h | 4 | ||||
-rw-r--r-- | arch/s390/kernel/signal.c | 5 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 2 |
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 | |||
191 | static inline void __load_psw_mask (unsigned long mask) | 190 | static 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 | */ | ||
218 | static 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 |