Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ccf45caf authored by Martin Schwidefsky's avatar Martin Schwidefsky
Browse files

[S390] addressing mode limits and psw address wrapping



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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 20b40a79
Loading
Loading
Loading
Loading
+21 −1
Original line number Original line Diff line number Diff line
@@ -187,7 +187,6 @@ static inline void __load_psw(psw_t psw)
 * Set PSW mask to specified value, while leaving the
 * Set PSW mask to specified value, while leaving the
 * PSW addr pointing to the next instruction.
 * PSW addr pointing to the next instruction.
 */
 */

static inline void __load_psw_mask (unsigned long mask)
static inline void __load_psw_mask (unsigned long mask)
{
{
	unsigned long addr;
	unsigned long addr;
@@ -213,6 +212,27 @@ static inline void __load_psw_mask (unsigned long mask)
#endif /* __s390x__ */
#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
 * Function to stop a processor until an interruption occurred
 */
 */
+4 −0
Original line number Original line Diff line number Diff line
@@ -236,6 +236,8 @@ typedef struct
#define PSW_MASK_ASC		0x0000C000UL
#define PSW_MASK_ASC		0x0000C000UL
#define PSW_MASK_CC		0x00003000UL
#define PSW_MASK_CC		0x00003000UL
#define PSW_MASK_PM		0x00000F00UL
#define PSW_MASK_PM		0x00000F00UL
#define PSW_MASK_EA		0x00000000UL
#define PSW_MASK_BA		0x00000000UL


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


#define PSW_ADDR_AMODE		0x0000000000000000UL
#define PSW_ADDR_AMODE		0x0000000000000000UL
#define PSW_ADDR_INSN		0xFFFFFFFFFFFFFFFFUL
#define PSW_ADDR_INSN		0xFFFFFFFFFFFFFFFFUL
+3 −2
Original line number Original line Diff line number Diff line
@@ -447,8 +447,9 @@ void do_signal(struct pt_regs *regs)
			/* fallthrough */
			/* fallthrough */
			case -ERESTARTNOINTR:
			case -ERESTARTNOINTR:
				regs->gprs[2] = regs->orig_gpr2;
				regs->gprs[2] = regs->orig_gpr2;
				regs->psw.addr = regs->psw.addr -
				regs->psw.addr =
					(regs->svc_code >> 16);
					__rewind_psw(regs->psw,
						     regs->svc_code >> 16);
				break;
				break;
			}
			}
			/* No longer in a system call */
			/* No longer in a system call */
+1 −1
Original line number Original line Diff line number Diff line
@@ -393,7 +393,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code,
	int fault;
	int fault;


	/* Protection exception is suppressing, decrement psw address. */
	/* 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
	 * Check for low-address protection.  This needs to be treated
	 * as a special case because the translation exception code
	 * as a special case because the translation exception code