Skip to content

Commit

Permalink
[S390] addressing mode limits and psw address wrapping
Browse files Browse the repository at this point in the history
An instruction with an address right below the adress limit for the
current addressing mode will wrap. The instruction restart logic in
the protection fault handler and the signal code need to follow the
wrapping rules to find the correct instruction address.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Martin Schwidefsky committed Oct 30, 2011
1 parent 20b40a7 commit ccf45ca
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 4 deletions.
22 changes: 21 additions & 1 deletion arch/s390/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ static inline void __load_psw(psw_t psw)
* Set PSW mask to specified value, while leaving the
* PSW addr pointing to the next instruction.
*/

static inline void __load_psw_mask (unsigned long mask)
{
unsigned long addr;
Expand All @@ -212,6 +211,27 @@ static inline void __load_psw_mask (unsigned long mask)
: "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
#endif /* __s390x__ */
}

/*
* Rewind PSW instruction address by specified number of bytes.
*/
static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
{
#ifndef __s390x__
if (psw.addr & PSW_ADDR_AMODE)
/* 31 bit mode */
return (psw.addr - ilc) | PSW_ADDR_AMODE;
/* 24 bit mode */
return (psw.addr - ilc) & ((1UL << 24) - 1);
#else
unsigned long mask;

mask = (psw.mask & PSW_MASK_EA) ? -1UL :
(psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 :
(1UL << 24) - 1;
return (psw.addr - ilc) & mask;
#endif
}

/*
* Function to stop a processor until an interruption occurred
Expand Down
4 changes: 4 additions & 0 deletions arch/s390/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ typedef struct
#define PSW_MASK_ASC 0x0000C000UL
#define PSW_MASK_CC 0x00003000UL
#define PSW_MASK_PM 0x00000F00UL
#define PSW_MASK_EA 0x00000000UL
#define PSW_MASK_BA 0x00000000UL

#define PSW_ADDR_AMODE 0x80000000UL
#define PSW_ADDR_INSN 0x7FFFFFFFUL
Expand All @@ -261,6 +263,8 @@ typedef struct
#define PSW_MASK_ASC 0x0000C00000000000UL
#define PSW_MASK_CC 0x0000300000000000UL
#define PSW_MASK_PM 0x00000F0000000000UL
#define PSW_MASK_EA 0x0000000100000000UL
#define PSW_MASK_BA 0x0000000080000000UL

#define PSW_ADDR_AMODE 0x0000000000000000UL
#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL
Expand Down
5 changes: 3 additions & 2 deletions arch/s390/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,9 @@ void do_signal(struct pt_regs *regs)
/* fallthrough */
case -ERESTARTNOINTR:
regs->gprs[2] = regs->orig_gpr2;
regs->psw.addr = regs->psw.addr -
(regs->svc_code >> 16);
regs->psw.addr =
__rewind_psw(regs->psw,
regs->svc_code >> 16);
break;
}
/* No longer in a system call */
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code,
int fault;

/* Protection exception is suppressing, decrement psw address. */
regs->psw.addr -= (pgm_int_code >> 16);
regs->psw.addr = __rewind_psw(regs->psw, pgm_int_code >> 16);
/*
* Check for low-address protection. This needs to be treated
* as a special case because the translation exception code
Expand Down

0 comments on commit ccf45ca

Please sign in to comment.