summaryrefslogtreecommitdiff
path: root/arch/s390/include
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2011-10-30 14:16:48 (GMT)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-10-30 14:16:43 (GMT)
commitccf45cafb0805978e6f13a672caca0e536e87cad (patch)
treef4abcadaf691ee952527ad434db3ab91b6e46e7f /arch/s390/include
parent20b40a794baf3b4b0320c0a77ce944d5d1a01f25 (diff)
downloadlinux-fsl-qoriq-ccf45cafb0805978e6f13a672caca0e536e87cad.tar.xz
[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: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/include')
-rw-r--r--arch/s390/include/asm/processor.h22
-rw-r--r--arch/s390/include/asm/ptrace.h4
2 files changed, 25 insertions, 1 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index a4b6229..306c93c 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)
* 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;
@@ -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
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 93c907b..2904cc6 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -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
@@ -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