aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2014-10-06 11:53:53 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-10-09 03:14:13 -0400
commit8070361799ae1e3f4ef347bd10f0a508ac10acfb (patch)
tree9846c0633cd28a86dc62eca55a4268fed513fcfd /arch
parent42f4dd613fe808676126472bbe1283e452201148 (diff)
s390: add support for vector extension
The vector extension introduces 32 128-bit vector registers and a set of instruction to operate on the vector registers. The kernel can control the use of vector registers for the problem state program with a bit in control register 0. Once enabled for a process the kernel needs to retain the content of the vector registers on context switch. The signal frame is extended to include the vector registers. Two new register sets NT_S390_VXRS_LOW and NT_S390_VXRS_HIGH are added to the regset interface for the debugger and core dumps. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/elf.h1
-rw-r--r--arch/s390/include/asm/lowcore.h10
-rw-r--r--arch/s390/include/asm/nmi.h2
-rw-r--r--arch/s390/include/asm/processor.h1
-rw-r--r--arch/s390/include/asm/setup.h3
-rw-r--r--arch/s390/include/asm/switch_to.h48
-rw-r--r--arch/s390/include/uapi/asm/sigcontext.h20
-rw-r--r--arch/s390/include/uapi/asm/types.h4
-rw-r--r--arch/s390/include/uapi/asm/ucontext.h15
-rw-r--r--arch/s390/kernel/compat_linux.h9
-rw-r--r--arch/s390/kernel/compat_signal.c212
-rw-r--r--arch/s390/kernel/early.c2
-rw-r--r--arch/s390/kernel/entry.h3
-rw-r--r--arch/s390/kernel/nmi.c16
-rw-r--r--arch/s390/kernel/pgm_check.S2
-rw-r--r--arch/s390/kernel/processor.c2
-rw-r--r--arch/s390/kernel/ptrace.c249
-rw-r--r--arch/s390/kernel/setup.c9
-rw-r--r--arch/s390/kernel/signal.c296
-rw-r--r--arch/s390/kernel/smp.c3
-rw-r--r--arch/s390/kernel/traps.c82
21 files changed, 802 insertions, 187 deletions
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 78f4f8711d58..27735ae06a78 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -102,6 +102,7 @@
102#define HWCAP_S390_ETF3EH 256 102#define HWCAP_S390_ETF3EH 256
103#define HWCAP_S390_HIGH_GPRS 512 103#define HWCAP_S390_HIGH_GPRS 512
104#define HWCAP_S390_TE 1024 104#define HWCAP_S390_TE 1024
105#define HWCAP_S390_VXRS 2048
105 106
106/* 107/*
107 * These are used to set parameters in the core dumps. 108 * These are used to set parameters in the core dumps.
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 4349197ab9df..d812cf1a8177 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -310,7 +310,10 @@ struct _lowcore {
310 310
311 /* Extended facility list */ 311 /* Extended facility list */
312 __u64 stfle_fac_list[32]; /* 0x0f00 */ 312 __u64 stfle_fac_list[32]; /* 0x0f00 */
313 __u8 pad_0x1000[0x11b8-0x1000]; /* 0x1000 */ 313 __u8 pad_0x1000[0x11b0-0x1000]; /* 0x1000 */
314
315 /* Pointer to vector register save area */
316 __u64 vector_save_area_addr; /* 0x11b0 */
314 317
315 /* 64 bit extparam used for pfault/diag 250: defined by architecture */ 318 /* 64 bit extparam used for pfault/diag 250: defined by architecture */
316 __u64 ext_params2; /* 0x11B8 */ 319 __u64 ext_params2; /* 0x11B8 */
@@ -334,9 +337,10 @@ struct _lowcore {
334 337
335 /* Transaction abort diagnostic block */ 338 /* Transaction abort diagnostic block */
336 __u8 pgm_tdb[256]; /* 0x1800 */ 339 __u8 pgm_tdb[256]; /* 0x1800 */
340 __u8 pad_0x1900[0x1c00-0x1900]; /* 0x1900 */
337 341
338 /* align to the top of the prefix area */ 342 /* Software defined save area for vector registers */
339 __u8 pad_0x1900[0x2000-0x1900]; /* 0x1900 */ 343 __u8 vector_save_area[1024]; /* 0x1c00 */
340} __packed; 344} __packed;
341 345
342#endif /* CONFIG_32BIT */ 346#endif /* CONFIG_32BIT */
diff --git a/arch/s390/include/asm/nmi.h b/arch/s390/include/asm/nmi.h
index 35f8ec185616..3027a5a72b74 100644
--- a/arch/s390/include/asm/nmi.h
+++ b/arch/s390/include/asm/nmi.h
@@ -38,7 +38,7 @@ struct mci {
38 __u32 pm : 1; /* 22 psw program mask and cc validity */ 38 __u32 pm : 1; /* 22 psw program mask and cc validity */
39 __u32 ia : 1; /* 23 psw instruction address validity */ 39 __u32 ia : 1; /* 23 psw instruction address validity */
40 __u32 fa : 1; /* 24 failing storage address validity */ 40 __u32 fa : 1; /* 24 failing storage address validity */
41 __u32 : 1; /* 25 */ 41 __u32 vr : 1; /* 25 vector register validity */
42 __u32 ec : 1; /* 26 external damage code validity */ 42 __u32 ec : 1; /* 26 external damage code validity */
43 __u32 fp : 1; /* 27 floating point register validity */ 43 __u32 fp : 1; /* 27 floating point register validity */
44 __u32 gr : 1; /* 28 general register validity */ 44 __u32 gr : 1; /* 28 general register validity */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 3d0871058306..d559bdb03d18 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -117,6 +117,7 @@ struct thread_struct {
117 int ri_signum; 117 int ri_signum;
118#ifdef CONFIG_64BIT 118#ifdef CONFIG_64BIT
119 unsigned char trap_tdb[256]; /* Transaction abort diagnose block */ 119 unsigned char trap_tdb[256]; /* Transaction abort diagnose block */
120 __vector128 *vxrs; /* Vector register save area */
120#endif 121#endif
121}; 122};
122 123
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index dbde7c236577..7736fdd72595 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -56,6 +56,7 @@ extern void detect_memory_memblock(void);
56#define MACHINE_FLAG_TOPOLOGY (1UL << 14) 56#define MACHINE_FLAG_TOPOLOGY (1UL << 14)
57#define MACHINE_FLAG_TE (1UL << 15) 57#define MACHINE_FLAG_TE (1UL << 15)
58#define MACHINE_FLAG_TLB_LC (1UL << 17) 58#define MACHINE_FLAG_TLB_LC (1UL << 17)
59#define MACHINE_FLAG_VX (1UL << 18)
59 60
60#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) 61#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
61#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) 62#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -78,6 +79,7 @@ extern void detect_memory_memblock(void);
78#define MACHINE_HAS_TOPOLOGY (0) 79#define MACHINE_HAS_TOPOLOGY (0)
79#define MACHINE_HAS_TE (0) 80#define MACHINE_HAS_TE (0)
80#define MACHINE_HAS_TLB_LC (0) 81#define MACHINE_HAS_TLB_LC (0)
82#define MACHINE_HAS_VX (0)
81#else /* CONFIG_64BIT */ 83#else /* CONFIG_64BIT */
82#define MACHINE_HAS_IEEE (1) 84#define MACHINE_HAS_IEEE (1)
83#define MACHINE_HAS_CSP (1) 85#define MACHINE_HAS_CSP (1)
@@ -90,6 +92,7 @@ extern void detect_memory_memblock(void);
90#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) 92#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
91#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE) 93#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
92#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC) 94#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC)
95#define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX)
93#endif /* CONFIG_64BIT */ 96#endif /* CONFIG_64BIT */
94 97
95/* 98/*
diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h
index 18ea9e3f8142..0e0109578021 100644
--- a/arch/s390/include/asm/switch_to.h
+++ b/arch/s390/include/asm/switch_to.h
@@ -103,6 +103,48 @@ static inline void restore_fp_regs(freg_t *fprs)
103 asm volatile("ld 15,%0" : : "Q" (fprs[15])); 103 asm volatile("ld 15,%0" : : "Q" (fprs[15]));
104} 104}
105 105
106static inline void save_vx_regs(__vector128 *vxrs)
107{
108 typedef struct { __vector128 _[__NUM_VXRS]; } addrtype;
109
110 asm volatile(
111 " la 1,%0\n"
112 " .word 0xe70f,0x1000,0x003e\n" /* vstm 0,15,0(1) */
113 " .word 0xe70f,0x1100,0x0c3e\n" /* vstm 16,31,256(1) */
114 : "=Q" (*(addrtype *) vxrs) : : "1");
115}
116
117static inline void restore_vx_regs(__vector128 *vxrs)
118{
119 typedef struct { __vector128 _[__NUM_VXRS]; } addrtype;
120
121 asm volatile(
122 " la 1,%0\n"
123 " .word 0xe70f,0x1000,0x0036\n" /* vlm 0,15,0(1) */
124 " .word 0xe70f,0x1100,0x0c36\n" /* vlm 16,31,256(1) */
125 : : "Q" (*(addrtype *) vxrs) : "1");
126}
127
128static inline void save_fp_vx_regs(struct task_struct *task)
129{
130#ifdef CONFIG_64BIT
131 if (task->thread.vxrs)
132 save_vx_regs(task->thread.vxrs);
133 else
134#endif
135 save_fp_regs(task->thread.fp_regs.fprs);
136}
137
138static inline void restore_fp_vx_regs(struct task_struct *task)
139{
140#ifdef CONFIG_64BIT
141 if (task->thread.vxrs)
142 restore_vx_regs(task->thread.vxrs);
143 else
144#endif
145 restore_fp_regs(task->thread.fp_regs.fprs);
146}
147
106static inline void save_access_regs(unsigned int *acrs) 148static inline void save_access_regs(unsigned int *acrs)
107{ 149{
108 typedef struct { int _[NUM_ACRS]; } acrstype; 150 typedef struct { int _[NUM_ACRS]; } acrstype;
@@ -120,16 +162,16 @@ static inline void restore_access_regs(unsigned int *acrs)
120#define switch_to(prev,next,last) do { \ 162#define switch_to(prev,next,last) do { \
121 if (prev->mm) { \ 163 if (prev->mm) { \
122 save_fp_ctl(&prev->thread.fp_regs.fpc); \ 164 save_fp_ctl(&prev->thread.fp_regs.fpc); \
123 save_fp_regs(prev->thread.fp_regs.fprs); \ 165 save_fp_vx_regs(prev); \
124 save_access_regs(&prev->thread.acrs[0]); \ 166 save_access_regs(&prev->thread.acrs[0]); \
125 save_ri_cb(prev->thread.ri_cb); \ 167 save_ri_cb(prev->thread.ri_cb); \
126 } \ 168 } \
127 if (next->mm) { \ 169 if (next->mm) { \
170 update_cr_regs(next); \
128 restore_fp_ctl(&next->thread.fp_regs.fpc); \ 171 restore_fp_ctl(&next->thread.fp_regs.fpc); \
129 restore_fp_regs(next->thread.fp_regs.fprs); \ 172 restore_fp_vx_regs(next); \
130 restore_access_regs(&next->thread.acrs[0]); \ 173 restore_access_regs(&next->thread.acrs[0]); \
131 restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \ 174 restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \
132 update_cr_regs(next); \
133 } \ 175 } \
134 prev = __switch_to(prev,next); \ 176 prev = __switch_to(prev,next); \
135} while (0) 177} while (0)
diff --git a/arch/s390/include/uapi/asm/sigcontext.h b/arch/s390/include/uapi/asm/sigcontext.h
index b30de9c01bbe..5f0b8d7ddb0b 100644
--- a/arch/s390/include/uapi/asm/sigcontext.h
+++ b/arch/s390/include/uapi/asm/sigcontext.h
@@ -7,10 +7,14 @@
7#define _ASM_S390_SIGCONTEXT_H 7#define _ASM_S390_SIGCONTEXT_H
8 8
9#include <linux/compiler.h> 9#include <linux/compiler.h>
10#include <linux/types.h>
10 11
11#define __NUM_GPRS 16 12#define __NUM_GPRS 16
12#define __NUM_FPRS 16 13#define __NUM_FPRS 16
13#define __NUM_ACRS 16 14#define __NUM_ACRS 16
15#define __NUM_VXRS 32
16#define __NUM_VXRS_LOW 16
17#define __NUM_VXRS_HIGH 16
14 18
15#ifndef __s390x__ 19#ifndef __s390x__
16 20
@@ -59,6 +63,16 @@ typedef struct
59 _s390_fp_regs fpregs; 63 _s390_fp_regs fpregs;
60} _sigregs; 64} _sigregs;
61 65
66typedef struct
67{
68#ifndef __s390x__
69 unsigned long gprs_high[__NUM_GPRS];
70#endif
71 unsigned long long vxrs_low[__NUM_VXRS_LOW];
72 __vector128 vxrs_high[__NUM_VXRS_HIGH];
73 unsigned char __reserved[128];
74} _sigregs_ext;
75
62struct sigcontext 76struct sigcontext
63{ 77{
64 unsigned long oldmask[_SIGCONTEXT_NSIG_WORDS]; 78 unsigned long oldmask[_SIGCONTEXT_NSIG_WORDS];
diff --git a/arch/s390/include/uapi/asm/types.h b/arch/s390/include/uapi/asm/types.h
index 038f2b9178a4..3c3951e3415b 100644
--- a/arch/s390/include/uapi/asm/types.h
+++ b/arch/s390/include/uapi/asm/types.h
@@ -17,6 +17,10 @@
17typedef unsigned long addr_t; 17typedef unsigned long addr_t;
18typedef __signed__ long saddr_t; 18typedef __signed__ long saddr_t;
19 19
20typedef struct {
21 __u32 u[4];
22} __vector128;
23
20#endif /* __ASSEMBLY__ */ 24#endif /* __ASSEMBLY__ */
21 25
22#endif /* _UAPI_S390_TYPES_H */ 26#endif /* _UAPI_S390_TYPES_H */
diff --git a/arch/s390/include/uapi/asm/ucontext.h b/arch/s390/include/uapi/asm/ucontext.h
index 3e077b2a4705..64a69aa5dde0 100644
--- a/arch/s390/include/uapi/asm/ucontext.h
+++ b/arch/s390/include/uapi/asm/ucontext.h
@@ -7,10 +7,15 @@
7#ifndef _ASM_S390_UCONTEXT_H 7#ifndef _ASM_S390_UCONTEXT_H
8#define _ASM_S390_UCONTEXT_H 8#define _ASM_S390_UCONTEXT_H
9 9
10#define UC_EXTENDED 0x00000001 10#define UC_GPRS_HIGH 1 /* uc_mcontext_ext has valid high gprs */
11 11#define UC_VXRS 2 /* uc_mcontext_ext has valid vector regs */
12#ifndef __s390x__
13 12
13/*
14 * The struct ucontext_extended describes how the registers are stored
15 * on a rt signal frame. Please note that the structure is not fixed,
16 * if new CPU registers are added to the user state the size of the
17 * struct ucontext_extended will increase.
18 */
14struct ucontext_extended { 19struct ucontext_extended {
15 unsigned long uc_flags; 20 unsigned long uc_flags;
16 struct ucontext *uc_link; 21 struct ucontext *uc_link;
@@ -19,11 +24,9 @@ struct ucontext_extended {
19 sigset_t uc_sigmask; 24 sigset_t uc_sigmask;
20 /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */ 25 /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */
21 unsigned char __unused[128 - sizeof(sigset_t)]; 26 unsigned char __unused[128 - sizeof(sigset_t)];
22 unsigned long uc_gprs_high[16]; 27 _sigregs_ext uc_mcontext_ext;
23}; 28};
24 29
25#endif
26
27struct ucontext { 30struct ucontext {
28 unsigned long uc_flags; 31 unsigned long uc_flags;
29 struct ucontext *uc_link; 32 struct ucontext *uc_link;
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index 70d4b7c4beaa..a0a886c04977 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -50,6 +50,14 @@ typedef struct
50 _s390_fp_regs32 fpregs; 50 _s390_fp_regs32 fpregs;
51} _sigregs32; 51} _sigregs32;
52 52
53typedef struct
54{
55 __u32 gprs_high[__NUM_GPRS];
56 __u64 vxrs_low[__NUM_VXRS_LOW];
57 __vector128 vxrs_high[__NUM_VXRS_HIGH];
58 __u8 __reserved[128];
59} _sigregs_ext32;
60
53#define _SIGCONTEXT_NSIG32 64 61#define _SIGCONTEXT_NSIG32 64
54#define _SIGCONTEXT_NSIG_BPW32 32 62#define _SIGCONTEXT_NSIG_BPW32 32
55#define __SIGNAL_FRAMESIZE32 96 63#define __SIGNAL_FRAMESIZE32 96
@@ -72,6 +80,7 @@ struct ucontext32 {
72 compat_sigset_t uc_sigmask; 80 compat_sigset_t uc_sigmask;
73 /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */ 81 /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */
74 unsigned char __unused[128 - sizeof(compat_sigset_t)]; 82 unsigned char __unused[128 - sizeof(compat_sigset_t)];
83 _sigregs_ext32 uc_mcontext_ext;
75}; 84};
76 85
77struct stat64_emu31; 86struct stat64_emu31;
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 598b0b42668b..009f5eb11125 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -36,17 +36,16 @@ typedef struct
36 struct sigcontext32 sc; 36 struct sigcontext32 sc;
37 _sigregs32 sregs; 37 _sigregs32 sregs;
38 int signo; 38 int signo;
39 __u32 gprs_high[NUM_GPRS]; 39 _sigregs_ext32 sregs_ext;
40 __u8 retcode[S390_SYSCALL_SIZE]; 40 __u16 svc_insn; /* Offset of svc_insn is NOT fixed! */
41} sigframe32; 41} sigframe32;
42 42
43typedef struct 43typedef struct
44{ 44{
45 __u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; 45 __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
46 __u8 retcode[S390_SYSCALL_SIZE]; 46 __u16 svc_insn;
47 compat_siginfo_t info; 47 compat_siginfo_t info;
48 struct ucontext32 uc; 48 struct ucontext32 uc;
49 __u32 gprs_high[NUM_GPRS];
50} rt_sigframe32; 49} rt_sigframe32;
51 50
52int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) 51int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
@@ -151,6 +150,38 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
151 return err ? -EFAULT : 0; 150 return err ? -EFAULT : 0;
152} 151}
153 152
153/* Store registers needed to create the signal frame */
154static void store_sigregs(void)
155{
156 int i;
157
158 save_access_regs(current->thread.acrs);
159 save_fp_ctl(&current->thread.fp_regs.fpc);
160 if (current->thread.vxrs) {
161 save_vx_regs(current->thread.vxrs);
162 for (i = 0; i < __NUM_FPRS; i++)
163 current->thread.fp_regs.fprs[i] =
164 *(freg_t *)(current->thread.vxrs + i);
165 } else
166 save_fp_regs(current->thread.fp_regs.fprs);
167}
168
169/* Load registers after signal return */
170static void load_sigregs(void)
171{
172 int i;
173
174 restore_access_regs(current->thread.acrs);
175 /* restore_fp_ctl is done in restore_sigregs */
176 if (current->thread.vxrs) {
177 for (i = 0; i < __NUM_FPRS; i++)
178 *(freg_t *)(current->thread.vxrs + i) =
179 current->thread.fp_regs.fprs[i];
180 restore_vx_regs(current->thread.vxrs);
181 } else
182 restore_fp_regs(current->thread.fp_regs.fprs);
183}
184
154static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs) 185static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
155{ 186{
156 _sigregs32 user_sregs; 187 _sigregs32 user_sregs;
@@ -163,11 +194,8 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
163 (__u32)(regs->psw.mask & PSW_MASK_BA); 194 (__u32)(regs->psw.mask & PSW_MASK_BA);
164 for (i = 0; i < NUM_GPRS; i++) 195 for (i = 0; i < NUM_GPRS; i++)
165 user_sregs.regs.gprs[i] = (__u32) regs->gprs[i]; 196 user_sregs.regs.gprs[i] = (__u32) regs->gprs[i];
166 save_access_regs(current->thread.acrs);
167 memcpy(&user_sregs.regs.acrs, current->thread.acrs, 197 memcpy(&user_sregs.regs.acrs, current->thread.acrs,
168 sizeof(user_sregs.regs.acrs)); 198 sizeof(user_sregs.regs.acrs));
169 save_fp_ctl(&current->thread.fp_regs.fpc);
170 save_fp_regs(current->thread.fp_regs.fprs);
171 memcpy(&user_sregs.fpregs, &current->thread.fp_regs, 199 memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
172 sizeof(user_sregs.fpregs)); 200 sizeof(user_sregs.fpregs));
173 if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32))) 201 if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32)))
@@ -207,37 +235,67 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
207 regs->gprs[i] = (__u64) user_sregs.regs.gprs[i]; 235 regs->gprs[i] = (__u64) user_sregs.regs.gprs[i];
208 memcpy(&current->thread.acrs, &user_sregs.regs.acrs, 236 memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
209 sizeof(current->thread.acrs)); 237 sizeof(current->thread.acrs));
210 restore_access_regs(current->thread.acrs);
211 238
212 memcpy(&current->thread.fp_regs, &user_sregs.fpregs, 239 memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
213 sizeof(current->thread.fp_regs)); 240 sizeof(current->thread.fp_regs));
214 241
215 restore_fp_regs(current->thread.fp_regs.fprs);
216 clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */ 242 clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */
217 return 0; 243 return 0;
218} 244}
219 245
220static int save_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs) 246static int save_sigregs_ext32(struct pt_regs *regs,
247 _sigregs_ext32 __user *sregs_ext)
221{ 248{
222 __u32 gprs_high[NUM_GPRS]; 249 __u32 gprs_high[NUM_GPRS];
250 __u64 vxrs[__NUM_VXRS_LOW];
223 int i; 251 int i;
224 252
253 /* Save high gprs to signal stack */
225 for (i = 0; i < NUM_GPRS; i++) 254 for (i = 0; i < NUM_GPRS; i++)
226 gprs_high[i] = regs->gprs[i] >> 32; 255 gprs_high[i] = regs->gprs[i] >> 32;
227 if (__copy_to_user(uregs, &gprs_high, sizeof(gprs_high))) 256 if (__copy_to_user(&sregs_ext->gprs_high, &gprs_high,
257 sizeof(sregs_ext->gprs_high)))
228 return -EFAULT; 258 return -EFAULT;
259
260 /* Save vector registers to signal stack */
261 if (current->thread.vxrs) {
262 for (i = 0; i < __NUM_VXRS_LOW; i++)
263 vxrs[i] = *((__u64 *)(current->thread.vxrs + i) + 1);
264 if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
265 sizeof(sregs_ext->vxrs_low)) ||
266 __copy_to_user(&sregs_ext->vxrs_high,
267 current->thread.vxrs + __NUM_VXRS_LOW,
268 sizeof(sregs_ext->vxrs_high)))
269 return -EFAULT;
270 }
229 return 0; 271 return 0;
230} 272}
231 273
232static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs) 274static int restore_sigregs_ext32(struct pt_regs *regs,
275 _sigregs_ext32 __user *sregs_ext)
233{ 276{
234 __u32 gprs_high[NUM_GPRS]; 277 __u32 gprs_high[NUM_GPRS];
278 __u64 vxrs[__NUM_VXRS_LOW];
235 int i; 279 int i;
236 280
237 if (__copy_from_user(&gprs_high, uregs, sizeof(gprs_high))) 281 /* Restore high gprs from signal stack */
282 if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high,
283 sizeof(&sregs_ext->gprs_high)))
238 return -EFAULT; 284 return -EFAULT;
239 for (i = 0; i < NUM_GPRS; i++) 285 for (i = 0; i < NUM_GPRS; i++)
240 *(__u32 *)&regs->gprs[i] = gprs_high[i]; 286 *(__u32 *)&regs->gprs[i] = gprs_high[i];
287
288 /* Restore vector registers from signal stack */
289 if (current->thread.vxrs) {
290 if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
291 sizeof(sregs_ext->vxrs_low)) ||
292 __copy_from_user(current->thread.vxrs + __NUM_VXRS_LOW,
293 &sregs_ext->vxrs_high,
294 sizeof(sregs_ext->vxrs_high)))
295 return -EFAULT;
296 for (i = 0; i < __NUM_VXRS_LOW; i++)
297 *((__u64 *)(current->thread.vxrs + i) + 1) = vxrs[i];
298 }
241 return 0; 299 return 0;
242} 300}
243 301
@@ -252,8 +310,9 @@ COMPAT_SYSCALL_DEFINE0(sigreturn)
252 set_current_blocked(&set); 310 set_current_blocked(&set);
253 if (restore_sigregs32(regs, &frame->sregs)) 311 if (restore_sigregs32(regs, &frame->sregs))
254 goto badframe; 312 goto badframe;
255 if (restore_sigregs_gprs_high(regs, frame->gprs_high)) 313 if (restore_sigregs_ext32(regs, &frame->sregs_ext))
256 goto badframe; 314 goto badframe;
315 load_sigregs();
257 return regs->gprs[2]; 316 return regs->gprs[2];
258badframe: 317badframe:
259 force_sig(SIGSEGV, current); 318 force_sig(SIGSEGV, current);
@@ -269,12 +328,13 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
269 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 328 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
270 goto badframe; 329 goto badframe;
271 set_current_blocked(&set); 330 set_current_blocked(&set);
331 if (compat_restore_altstack(&frame->uc.uc_stack))
332 goto badframe;
272 if (restore_sigregs32(regs, &frame->uc.uc_mcontext)) 333 if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
273 goto badframe; 334 goto badframe;
274 if (restore_sigregs_gprs_high(regs, frame->gprs_high)) 335 if (restore_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
275 goto badframe; 336 goto badframe;
276 if (compat_restore_altstack(&frame->uc.uc_stack)) 337 load_sigregs();
277 goto badframe;
278 return regs->gprs[2]; 338 return regs->gprs[2];
279badframe: 339badframe:
280 force_sig(SIGSEGV, current); 340 force_sig(SIGSEGV, current);
@@ -324,37 +384,64 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set,
324 struct pt_regs *regs) 384 struct pt_regs *regs)
325{ 385{
326 int sig = ksig->sig; 386 int sig = ksig->sig;
327 sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(sigframe32)); 387 sigframe32 __user *frame;
328 388 struct sigcontext32 sc;
389 unsigned long restorer;
390 size_t frame_size;
391
392 /*
393 * gprs_high are always present for 31-bit compat tasks.
394 * The space for vector registers is only allocated if
395 * the machine supports it
396 */
397 frame_size = sizeof(*frame) - sizeof(frame->sregs_ext.__reserved);
398 if (!MACHINE_HAS_VX)
399 frame_size -= sizeof(frame->sregs_ext.vxrs_low) +
400 sizeof(frame->sregs_ext.vxrs_high);
401 frame = get_sigframe(&ksig->ka, regs, frame_size);
329 if (frame == (void __user *) -1UL) 402 if (frame == (void __user *) -1UL)
330 return -EFAULT; 403 return -EFAULT;
331 404
332 if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32)) 405 /* Set up backchain. */
406 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
407 return -EFAULT;
408
409 /* Create struct sigcontext32 on the signal stack */
410 memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32);
411 sc.sregs = (__u32)(unsigned long __force) &frame->sregs;
412 if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc)))
333 return -EFAULT; 413 return -EFAULT;
334 414
415 /* Store registers needed to create the signal frame */
416 store_sigregs();
417
418 /* Create _sigregs32 on the signal stack */
335 if (save_sigregs32(regs, &frame->sregs)) 419 if (save_sigregs32(regs, &frame->sregs))
336 return -EFAULT; 420 return -EFAULT;
337 if (save_sigregs_gprs_high(regs, frame->gprs_high)) 421
422 /* Place signal number on stack to allow backtrace from handler. */
423 if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
338 return -EFAULT; 424 return -EFAULT;
339 if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs)) 425
426 /* Create _sigregs_ext32 on the signal stack */
427 if (save_sigregs_ext32(regs, &frame->sregs_ext))
340 return -EFAULT; 428 return -EFAULT;
341 429
342 /* Set up to return from userspace. If provided, use a stub 430 /* Set up to return from userspace. If provided, use a stub
343 already in userspace. */ 431 already in userspace. */
344 if (ksig->ka.sa.sa_flags & SA_RESTORER) { 432 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
345 regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE; 433 restorer = (unsigned long __force)
434 ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
346 } else { 435 } else {
347 regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE; 436 /* Signal frames without vectors registers are short ! */
348 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, 437 __u16 __user *svc = (void *) frame + frame_size - 2;
349 (u16 __force __user *)(frame->retcode))) 438 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc))
350 return -EFAULT; 439 return -EFAULT;
440 restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE;
351 } 441 }
352 442
353 /* Set up backchain. */
354 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
355 return -EFAULT;
356
357 /* Set up registers for signal handler */ 443 /* Set up registers for signal handler */
444 regs->gprs[14] = restorer;
358 regs->gprs[15] = (__force __u64) frame; 445 regs->gprs[15] = (__force __u64) frame;
359 /* Force 31 bit amode and default user address space control. */ 446 /* Force 31 bit amode and default user address space control. */
360 regs->psw.mask = PSW_MASK_BA | 447 regs->psw.mask = PSW_MASK_BA |
@@ -375,50 +462,69 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set,
375 regs->gprs[6] = task_thread_info(current)->last_break; 462 regs->gprs[6] = task_thread_info(current)->last_break;
376 } 463 }
377 464
378 /* Place signal number on stack to allow backtrace from handler. */
379 if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
380 return -EFAULT;
381 return 0; 465 return 0;
382} 466}
383 467
384static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set, 468static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
385 struct pt_regs *regs) 469 struct pt_regs *regs)
386{ 470{
387 int err = 0; 471 rt_sigframe32 __user *frame;
388 rt_sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe32)); 472 unsigned long restorer;
389 473 size_t frame_size;
474 u32 uc_flags;
475
476 frame_size = sizeof(*frame) -
477 sizeof(frame->uc.uc_mcontext_ext.__reserved);
478 /*
479 * gprs_high are always present for 31-bit compat tasks.
480 * The space for vector registers is only allocated if
481 * the machine supports it
482 */
483 uc_flags = UC_GPRS_HIGH;
484 if (MACHINE_HAS_VX) {
485 if (current->thread.vxrs)
486 uc_flags |= UC_VXRS;
487 } else
488 frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) +
489 sizeof(frame->uc.uc_mcontext_ext.vxrs_high);
490 frame = get_sigframe(&ksig->ka, regs, frame_size);
390 if (frame == (void __user *) -1UL) 491 if (frame == (void __user *) -1UL)
391 return -EFAULT; 492 return -EFAULT;
392 493
393 if (copy_siginfo_to_user32(&frame->info, &ksig->info)) 494 /* Set up backchain. */
394 return -EFAULT; 495 if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
395
396 /* Create the ucontext. */
397 err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
398 err |= __put_user(0, &frame->uc.uc_link);
399 err |= __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]);
400 err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
401 err |= save_sigregs_gprs_high(regs, frame->gprs_high);
402 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
403 if (err)
404 return -EFAULT; 496 return -EFAULT;
405 497
406 /* Set up to return from userspace. If provided, use a stub 498 /* Set up to return from userspace. If provided, use a stub
407 already in userspace. */ 499 already in userspace. */
408 if (ksig->ka.sa.sa_flags & SA_RESTORER) { 500 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
409 regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE; 501 restorer = (unsigned long __force)
502 ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
410 } else { 503 } else {
411 regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE; 504 __u16 __user *svc = &frame->svc_insn;
412 if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, 505 if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc))
413 (u16 __force __user *)(frame->retcode)))
414 return -EFAULT; 506 return -EFAULT;
507 restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE;
415 } 508 }
416 509
417 /* Set up backchain. */ 510 /* Create siginfo on the signal stack */
418 if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame)) 511 if (copy_siginfo_to_user32(&frame->info, &ksig->info))
512 return -EFAULT;
513
514 /* Store registers needed to create the signal frame */
515 store_sigregs();
516
517 /* Create ucontext on the signal stack. */
518 if (__put_user(uc_flags, &frame->uc.uc_flags) ||
519 __put_user(0, &frame->uc.uc_link) ||
520 __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
521 save_sigregs32(regs, &frame->uc.uc_mcontext) ||
522 __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) ||
523 save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
419 return -EFAULT; 524 return -EFAULT;
420 525
421 /* Set up registers for signal handler */ 526 /* Set up registers for signal handler */
527 regs->gprs[14] = restorer;
422 regs->gprs[15] = (__force __u64) frame; 528 regs->gprs[15] = (__force __u64) frame;
423 /* Force 31 bit amode and default user address space control. */ 529 /* Force 31 bit amode and default user address space control. */
424 regs->psw.mask = PSW_MASK_BA | 530 regs->psw.mask = PSW_MASK_BA |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index f6c66b5d0cfa..cef2879edff3 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -392,6 +392,8 @@ static __init void detect_machine_facilities(void)
392 S390_lowcore.machine_flags |= MACHINE_FLAG_TE; 392 S390_lowcore.machine_flags |= MACHINE_FLAG_TE;
393 if (test_facility(51)) 393 if (test_facility(51))
394 S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC; 394 S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
395 if (test_facility(129))
396 S390_lowcore.machine_flags |= MACHINE_FLAG_VX;
395#endif 397#endif
396} 398}
397 399
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index cd68869f9504..0554b9771c9f 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -21,6 +21,8 @@ void psw_idle(struct s390_idle_data *, unsigned long);
21asmlinkage long do_syscall_trace_enter(struct pt_regs *regs); 21asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
22asmlinkage void do_syscall_trace_exit(struct pt_regs *regs); 22asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
23 23
24int alloc_vector_registers(struct task_struct *tsk);
25
24void do_protection_exception(struct pt_regs *regs); 26void do_protection_exception(struct pt_regs *regs);
25void do_dat_exception(struct pt_regs *regs); 27void do_dat_exception(struct pt_regs *regs);
26 28
@@ -43,6 +45,7 @@ void special_op_exception(struct pt_regs *regs);
43void specification_exception(struct pt_regs *regs); 45void specification_exception(struct pt_regs *regs);
44void transaction_exception(struct pt_regs *regs); 46void transaction_exception(struct pt_regs *regs);
45void translation_exception(struct pt_regs *regs); 47void translation_exception(struct pt_regs *regs);
48void vector_exception(struct pt_regs *regs);
46 49
47void do_per_trap(struct pt_regs *regs); 50void do_per_trap(struct pt_regs *regs);
48void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str); 51void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str);
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index 210e1285f75a..db96b418160a 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -20,6 +20,7 @@
20#include <asm/cputime.h> 20#include <asm/cputime.h>
21#include <asm/nmi.h> 21#include <asm/nmi.h>
22#include <asm/crw.h> 22#include <asm/crw.h>
23#include <asm/switch_to.h>
23 24
24struct mcck_struct { 25struct mcck_struct {
25 int kill_task; 26 int kill_task;
@@ -163,6 +164,21 @@ static int notrace s390_revalidate_registers(struct mci *mci)
163 " ld 15,120(%0)\n" 164 " ld 15,120(%0)\n"
164 : : "a" (fpt_save_area)); 165 : : "a" (fpt_save_area));
165 } 166 }
167
168#ifdef CONFIG_64BIT
169 /* Revalidate vector registers */
170 if (MACHINE_HAS_VX && current->thread.vxrs) {
171 if (!mci->vr) {
172 /*
173 * Vector registers can't be restored and therefore
174 * the process needs to be terminated.
175 */
176 kill_task = 1;
177 }
178 restore_vx_regs((__vector128 *)
179 S390_lowcore.vector_save_area_addr);
180 }
181#endif
166 /* Revalidate access registers */ 182 /* Revalidate access registers */
167 asm volatile( 183 asm volatile(
168 " lam 0,15,0(%0)" 184 " lam 0,15,0(%0)"
diff --git a/arch/s390/kernel/pgm_check.S b/arch/s390/kernel/pgm_check.S
index 813ec7260878..f6f8886399f6 100644
--- a/arch/s390/kernel/pgm_check.S
+++ b/arch/s390/kernel/pgm_check.S
@@ -49,7 +49,7 @@ PGM_CHECK_DEFAULT /* 17 */
49PGM_CHECK_64BIT(transaction_exception) /* 18 */ 49PGM_CHECK_64BIT(transaction_exception) /* 18 */
50PGM_CHECK_DEFAULT /* 19 */ 50PGM_CHECK_DEFAULT /* 19 */
51PGM_CHECK_DEFAULT /* 1a */ 51PGM_CHECK_DEFAULT /* 1a */
52PGM_CHECK_DEFAULT /* 1b */ 52PGM_CHECK_64BIT(vector_exception) /* 1b */
53PGM_CHECK(space_switch_exception) /* 1c */ 53PGM_CHECK(space_switch_exception) /* 1c */
54PGM_CHECK(hfp_sqrt_exception) /* 1d */ 54PGM_CHECK(hfp_sqrt_exception) /* 1d */
55PGM_CHECK_DEFAULT /* 1e */ 55PGM_CHECK_DEFAULT /* 1e */
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 32587cc76306..edefead3b43a 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -39,7 +39,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
39{ 39{
40 static const char *hwcap_str[] = { 40 static const char *hwcap_str[] = {
41 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", 41 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
42 "edat", "etf3eh", "highgprs", "te" 42 "edat", "etf3eh", "highgprs", "te", "vx"
43 }; 43 };
44 unsigned long n = (unsigned long) v - 1; 44 unsigned long n = (unsigned long) v - 1;
45 int i; 45 int i;
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index fe99d6b3f185..0ecfdb3c6f8e 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -38,15 +38,6 @@
38#define CREATE_TRACE_POINTS 38#define CREATE_TRACE_POINTS
39#include <trace/events/syscalls.h> 39#include <trace/events/syscalls.h>
40 40
41enum s390_regset {
42 REGSET_GENERAL,
43 REGSET_FP,
44 REGSET_LAST_BREAK,
45 REGSET_TDB,
46 REGSET_SYSTEM_CALL,
47 REGSET_GENERAL_EXTENDED,
48};
49
50void update_cr_regs(struct task_struct *task) 41void update_cr_regs(struct task_struct *task)
51{ 42{
52 struct pt_regs *regs = task_pt_regs(task); 43 struct pt_regs *regs = task_pt_regs(task);
@@ -55,27 +46,39 @@ void update_cr_regs(struct task_struct *task)
55 46
56#ifdef CONFIG_64BIT 47#ifdef CONFIG_64BIT
57 /* Take care of the enable/disable of transactional execution. */ 48 /* Take care of the enable/disable of transactional execution. */
58 if (MACHINE_HAS_TE) { 49 if (MACHINE_HAS_TE || MACHINE_HAS_VX) {
59 unsigned long cr, cr_new; 50 unsigned long cr, cr_new;
60 51
61 __ctl_store(cr, 0, 0); 52 __ctl_store(cr, 0, 0);
62 /* Set or clear transaction execution TXC bit 8. */ 53 cr_new = cr;
63 cr_new = cr | (1UL << 55); 54 if (MACHINE_HAS_TE) {
64 if (task->thread.per_flags & PER_FLAG_NO_TE) 55 /* Set or clear transaction execution TXC bit 8. */
65 cr_new &= ~(1UL << 55); 56 cr_new |= (1UL << 55);
57 if (task->thread.per_flags & PER_FLAG_NO_TE)
58 cr_new &= ~(1UL << 55);
59 }
60 if (MACHINE_HAS_VX) {
61 /* Enable/disable of vector extension */
62 cr_new &= ~(1UL << 17);
63 if (task->thread.vxrs)
64 cr_new |= (1UL << 17);
65 }
66 if (cr_new != cr) 66 if (cr_new != cr)
67 __ctl_load(cr_new, 0, 0); 67 __ctl_load(cr_new, 0, 0);
68 /* Set or clear transaction execution TDC bits 62 and 63. */ 68 if (MACHINE_HAS_TE) {
69 __ctl_store(cr, 2, 2); 69 /* Set/clear transaction execution TDC bits 62/63. */
70 cr_new = cr & ~3UL; 70 __ctl_store(cr, 2, 2);
71 if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) { 71 cr_new = cr & ~3UL;
72 if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND) 72 if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
73 cr_new |= 1UL; 73 if (task->thread.per_flags &
74 else 74 PER_FLAG_TE_ABORT_RAND_TEND)
75 cr_new |= 2UL; 75 cr_new |= 1UL;
76 else
77 cr_new |= 2UL;
78 }
79 if (cr_new != cr)
80 __ctl_load(cr_new, 2, 2);
76 } 81 }
77 if (cr_new != cr)
78 __ctl_load(cr_new, 2, 2);
79 } 82 }
80#endif 83#endif
81 /* Copy user specified PER registers */ 84 /* Copy user specified PER registers */
@@ -926,7 +929,15 @@ static int s390_fpregs_get(struct task_struct *target,
926 save_fp_ctl(&target->thread.fp_regs.fpc); 929 save_fp_ctl(&target->thread.fp_regs.fpc);
927 save_fp_regs(target->thread.fp_regs.fprs); 930 save_fp_regs(target->thread.fp_regs.fprs);
928 } 931 }
932#ifdef CONFIG_64BIT
933 else if (target->thread.vxrs) {
934 int i;
929 935
936 for (i = 0; i < __NUM_VXRS_LOW; i++)
937 target->thread.fp_regs.fprs[i] =
938 *(freg_t *)(target->thread.vxrs + i);
939 }
940#endif
930 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 941 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
931 &target->thread.fp_regs, 0, -1); 942 &target->thread.fp_regs, 0, -1);
932} 943}
@@ -960,9 +971,20 @@ static int s390_fpregs_set(struct task_struct *target,
960 target->thread.fp_regs.fprs, 971 target->thread.fp_regs.fprs,
961 offsetof(s390_fp_regs, fprs), -1); 972 offsetof(s390_fp_regs, fprs), -1);
962 973
963 if (rc == 0 && target == current) { 974 if (rc == 0) {
964 restore_fp_ctl(&target->thread.fp_regs.fpc); 975 if (target == current) {
965 restore_fp_regs(target->thread.fp_regs.fprs); 976 restore_fp_ctl(&target->thread.fp_regs.fpc);
977 restore_fp_regs(target->thread.fp_regs.fprs);
978 }
979#ifdef CONFIG_64BIT
980 else if (target->thread.vxrs) {
981 int i;
982
983 for (i = 0; i < __NUM_VXRS_LOW; i++)
984 *(freg_t *)(target->thread.vxrs + i) =
985 target->thread.fp_regs.fprs[i];
986 }
987#endif
966 } 988 }
967 989
968 return rc; 990 return rc;
@@ -1018,6 +1040,95 @@ static int s390_tdb_set(struct task_struct *target,
1018 return 0; 1040 return 0;
1019} 1041}
1020 1042
1043static int s390_vxrs_active(struct task_struct *target,
1044 const struct user_regset *regset)
1045{
1046 return !!target->thread.vxrs;
1047}
1048
1049static int s390_vxrs_low_get(struct task_struct *target,
1050 const struct user_regset *regset,
1051 unsigned int pos, unsigned int count,
1052 void *kbuf, void __user *ubuf)
1053{
1054 __u64 vxrs[__NUM_VXRS_LOW];
1055 int i;
1056
1057 if (target->thread.vxrs) {
1058 if (target == current)
1059 save_vx_regs(target->thread.vxrs);
1060 for (i = 0; i < __NUM_VXRS_LOW; i++)
1061 vxrs[i] = *((__u64 *)(target->thread.vxrs + i) + 1);
1062 } else
1063 memset(vxrs, 0, sizeof(vxrs));
1064 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
1065}
1066
1067static int s390_vxrs_low_set(struct task_struct *target,
1068 const struct user_regset *regset,
1069 unsigned int pos, unsigned int count,
1070 const void *kbuf, const void __user *ubuf)
1071{
1072 __u64 vxrs[__NUM_VXRS_LOW];
1073 int i, rc;
1074
1075 if (!target->thread.vxrs) {
1076 rc = alloc_vector_registers(target);
1077 if (rc)
1078 return rc;
1079 } else if (target == current)
1080 save_vx_regs(target->thread.vxrs);
1081
1082 rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
1083 if (rc == 0) {
1084 for (i = 0; i < __NUM_VXRS_LOW; i++)
1085 *((__u64 *)(target->thread.vxrs + i) + 1) = vxrs[i];
1086 if (target == current)
1087 restore_vx_regs(target->thread.vxrs);
1088 }
1089
1090 return rc;
1091}
1092
1093static int s390_vxrs_high_get(struct task_struct *target,
1094 const struct user_regset *regset,
1095 unsigned int pos, unsigned int count,
1096 void *kbuf, void __user *ubuf)
1097{
1098 __vector128 vxrs[__NUM_VXRS_HIGH];
1099
1100 if (target->thread.vxrs) {
1101 if (target == current)
1102 save_vx_regs(target->thread.vxrs);
1103 memcpy(vxrs, target->thread.vxrs + __NUM_VXRS_LOW,
1104 sizeof(vxrs));
1105 } else
1106 memset(vxrs, 0, sizeof(vxrs));
1107 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
1108}
1109
1110static int s390_vxrs_high_set(struct task_struct *target,
1111 const struct user_regset *regset,
1112 unsigned int pos, unsigned int count,
1113 const void *kbuf, const void __user *ubuf)
1114{
1115 int rc;
1116
1117 if (!target->thread.vxrs) {
1118 rc = alloc_vector_registers(target);
1119 if (rc)
1120 return rc;
1121 } else if (target == current)
1122 save_vx_regs(target->thread.vxrs);
1123
1124 rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
1125 target->thread.vxrs + __NUM_VXRS_LOW, 0, -1);
1126 if (rc == 0 && target == current)
1127 restore_vx_regs(target->thread.vxrs);
1128
1129 return rc;
1130}
1131
1021#endif 1132#endif
1022 1133
1023static int s390_system_call_get(struct task_struct *target, 1134static int s390_system_call_get(struct task_struct *target,
@@ -1041,7 +1152,7 @@ static int s390_system_call_set(struct task_struct *target,
1041} 1152}
1042 1153
1043static const struct user_regset s390_regsets[] = { 1154static const struct user_regset s390_regsets[] = {
1044 [REGSET_GENERAL] = { 1155 {
1045 .core_note_type = NT_PRSTATUS, 1156 .core_note_type = NT_PRSTATUS,
1046 .n = sizeof(s390_regs) / sizeof(long), 1157 .n = sizeof(s390_regs) / sizeof(long),
1047 .size = sizeof(long), 1158 .size = sizeof(long),
@@ -1049,7 +1160,7 @@ static const struct user_regset s390_regsets[] = {
1049 .get = s390_regs_get, 1160 .get = s390_regs_get,
1050 .set = s390_regs_set, 1161 .set = s390_regs_set,
1051 }, 1162 },
1052 [REGSET_FP] = { 1163 {
1053 .core_note_type = NT_PRFPREG, 1164 .core_note_type = NT_PRFPREG,
1054 .n = sizeof(s390_fp_regs) / sizeof(long), 1165 .n = sizeof(s390_fp_regs) / sizeof(long),
1055 .size = sizeof(long), 1166 .size = sizeof(long),
@@ -1057,8 +1168,16 @@ static const struct user_regset s390_regsets[] = {
1057 .get = s390_fpregs_get, 1168 .get = s390_fpregs_get,
1058 .set = s390_fpregs_set, 1169 .set = s390_fpregs_set,
1059 }, 1170 },
1171 {
1172 .core_note_type = NT_S390_SYSTEM_CALL,
1173 .n = 1,
1174 .size = sizeof(unsigned int),
1175 .align = sizeof(unsigned int),
1176 .get = s390_system_call_get,
1177 .set = s390_system_call_set,
1178 },
1060#ifdef CONFIG_64BIT 1179#ifdef CONFIG_64BIT
1061 [REGSET_LAST_BREAK] = { 1180 {
1062 .core_note_type = NT_S390_LAST_BREAK, 1181 .core_note_type = NT_S390_LAST_BREAK,
1063 .n = 1, 1182 .n = 1,
1064 .size = sizeof(long), 1183 .size = sizeof(long),
@@ -1066,7 +1185,7 @@ static const struct user_regset s390_regsets[] = {
1066 .get = s390_last_break_get, 1185 .get = s390_last_break_get,
1067 .set = s390_last_break_set, 1186 .set = s390_last_break_set,
1068 }, 1187 },
1069 [REGSET_TDB] = { 1188 {
1070 .core_note_type = NT_S390_TDB, 1189 .core_note_type = NT_S390_TDB,
1071 .n = 1, 1190 .n = 1,
1072 .size = 256, 1191 .size = 256,
@@ -1074,15 +1193,25 @@ static const struct user_regset s390_regsets[] = {
1074 .get = s390_tdb_get, 1193 .get = s390_tdb_get,
1075 .set = s390_tdb_set, 1194 .set = s390_tdb_set,
1076 }, 1195 },
1077#endif 1196 {
1078 [REGSET_SYSTEM_CALL] = { 1197 .core_note_type = NT_S390_VXRS_LOW,
1079 .core_note_type = NT_S390_SYSTEM_CALL, 1198 .n = __NUM_VXRS_LOW,
1080 .n = 1, 1199 .size = sizeof(__u64),
1081 .size = sizeof(unsigned int), 1200 .align = sizeof(__u64),
1082 .align = sizeof(unsigned int), 1201 .active = s390_vxrs_active,
1083 .get = s390_system_call_get, 1202 .get = s390_vxrs_low_get,
1084 .set = s390_system_call_set, 1203 .set = s390_vxrs_low_set,
1204 },
1205 {
1206 .core_note_type = NT_S390_VXRS_HIGH,
1207 .n = __NUM_VXRS_HIGH,
1208 .size = sizeof(__vector128),
1209 .align = sizeof(__vector128),
1210 .active = s390_vxrs_active,
1211 .get = s390_vxrs_high_get,
1212 .set = s390_vxrs_high_set,
1085 }, 1213 },
1214#endif
1086}; 1215};
1087 1216
1088static const struct user_regset_view user_s390_view = { 1217static const struct user_regset_view user_s390_view = {
@@ -1247,7 +1376,7 @@ static int s390_compat_last_break_set(struct task_struct *target,
1247} 1376}
1248 1377
1249static const struct user_regset s390_compat_regsets[] = { 1378static const struct user_regset s390_compat_regsets[] = {
1250 [REGSET_GENERAL] = { 1379 {
1251 .core_note_type = NT_PRSTATUS, 1380 .core_note_type = NT_PRSTATUS,
1252 .n = sizeof(s390_compat_regs) / sizeof(compat_long_t), 1381 .n = sizeof(s390_compat_regs) / sizeof(compat_long_t),
1253 .size = sizeof(compat_long_t), 1382 .size = sizeof(compat_long_t),
@@ -1255,7 +1384,7 @@ static const struct user_regset s390_compat_regsets[] = {
1255 .get = s390_compat_regs_get, 1384 .get = s390_compat_regs_get,
1256 .set = s390_compat_regs_set, 1385 .set = s390_compat_regs_set,
1257 }, 1386 },
1258 [REGSET_FP] = { 1387 {
1259 .core_note_type = NT_PRFPREG, 1388 .core_note_type = NT_PRFPREG,
1260 .n = sizeof(s390_fp_regs) / sizeof(compat_long_t), 1389 .n = sizeof(s390_fp_regs) / sizeof(compat_long_t),
1261 .size = sizeof(compat_long_t), 1390 .size = sizeof(compat_long_t),
@@ -1263,7 +1392,15 @@ static const struct user_regset s390_compat_regsets[] = {
1263 .get = s390_fpregs_get, 1392 .get = s390_fpregs_get,
1264 .set = s390_fpregs_set, 1393 .set = s390_fpregs_set,
1265 }, 1394 },
1266 [REGSET_LAST_BREAK] = { 1395 {
1396 .core_note_type = NT_S390_SYSTEM_CALL,
1397 .n = 1,
1398 .size = sizeof(compat_uint_t),
1399 .align = sizeof(compat_uint_t),
1400 .get = s390_system_call_get,
1401 .set = s390_system_call_set,
1402 },
1403 {
1267 .core_note_type = NT_S390_LAST_BREAK, 1404 .core_note_type = NT_S390_LAST_BREAK,
1268 .n = 1, 1405 .n = 1,
1269 .size = sizeof(long), 1406 .size = sizeof(long),
@@ -1271,7 +1408,7 @@ static const struct user_regset s390_compat_regsets[] = {
1271 .get = s390_compat_last_break_get, 1408 .get = s390_compat_last_break_get,
1272 .set = s390_compat_last_break_set, 1409 .set = s390_compat_last_break_set,
1273 }, 1410 },
1274 [REGSET_TDB] = { 1411 {
1275 .core_note_type = NT_S390_TDB, 1412 .core_note_type = NT_S390_TDB,
1276 .n = 1, 1413 .n = 1,
1277 .size = 256, 1414 .size = 256,
@@ -1279,15 +1416,25 @@ static const struct user_regset s390_compat_regsets[] = {
1279 .get = s390_tdb_get, 1416 .get = s390_tdb_get,
1280 .set = s390_tdb_set, 1417 .set = s390_tdb_set,
1281 }, 1418 },
1282 [REGSET_SYSTEM_CALL] = { 1419 {
1283 .core_note_type = NT_S390_SYSTEM_CALL, 1420 .core_note_type = NT_S390_VXRS_LOW,
1284 .n = 1, 1421 .n = __NUM_VXRS_LOW,
1285 .size = sizeof(compat_uint_t), 1422 .size = sizeof(__u64),
1286 .align = sizeof(compat_uint_t), 1423 .align = sizeof(__u64),
1287 .get = s390_system_call_get, 1424 .active = s390_vxrs_active,
1288 .set = s390_system_call_set, 1425 .get = s390_vxrs_low_get,
1426 .set = s390_vxrs_low_set,
1427 },
1428 {
1429 .core_note_type = NT_S390_VXRS_HIGH,
1430 .n = __NUM_VXRS_HIGH,
1431 .size = sizeof(__vector128),
1432 .align = sizeof(__vector128),
1433 .active = s390_vxrs_active,
1434 .get = s390_vxrs_high_get,
1435 .set = s390_vxrs_high_set,
1289 }, 1436 },
1290 [REGSET_GENERAL_EXTENDED] = { 1437 {
1291 .core_note_type = NT_S390_HIGH_GPRS, 1438 .core_note_type = NT_S390_HIGH_GPRS,
1292 .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t), 1439 .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
1293 .size = sizeof(compat_long_t), 1440 .size = sizeof(compat_long_t),
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index cdfc060dd319..e80d9ff9a56d 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -343,6 +343,9 @@ static void __init setup_lowcore(void)
343 __ctl_set_bit(14, 29); 343 __ctl_set_bit(14, 29);
344 } 344 }
345#else 345#else
346 if (MACHINE_HAS_VX)
347 lc->vector_save_area_addr =
348 (unsigned long) &lc->vector_save_area;
346 lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; 349 lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
347#endif 350#endif
348 lc->sync_enter_timer = S390_lowcore.sync_enter_timer; 351 lc->sync_enter_timer = S390_lowcore.sync_enter_timer;
@@ -765,6 +768,12 @@ static void __init setup_hwcaps(void)
765 */ 768 */
766 if (test_facility(50) && test_facility(73)) 769 if (test_facility(50) && test_facility(73))
767 elf_hwcap |= HWCAP_S390_TE; 770 elf_hwcap |= HWCAP_S390_TE;
771
772 /*
773 * Vector extension HWCAP_S390_VXRS is bit 11.
774 */
775 if (test_facility(129))
776 elf_hwcap |= HWCAP_S390_VXRS;
768#endif 777#endif
769 778
770 get_cpu_id(&cpu_id); 779 get_cpu_id(&cpu_id);
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 469c4c6d9182..0c1a0ff0a558 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -31,30 +31,117 @@
31#include <asm/switch_to.h> 31#include <asm/switch_to.h>
32#include "entry.h" 32#include "entry.h"
33 33
34typedef struct 34/*
35 * Layout of an old-style signal-frame:
36 * -----------------------------------------
37 * | save area (_SIGNAL_FRAMESIZE) |
38 * -----------------------------------------
39 * | struct sigcontext |
40 * | oldmask |
41 * | _sigregs * |
42 * -----------------------------------------
43 * | _sigregs with |
44 * | _s390_regs_common |
45 * | _s390_fp_regs |
46 * -----------------------------------------
47 * | int signo |
48 * -----------------------------------------
49 * | _sigregs_ext with |
50 * | gprs_high 64 byte (opt) |
51 * | vxrs_low 128 byte (opt) |
52 * | vxrs_high 256 byte (opt) |
53 * | reserved 128 byte (opt) |
54 * -----------------------------------------
55 * | __u16 svc_insn |
56 * -----------------------------------------
57 * The svc_insn entry with the sigreturn system call opcode does not
58 * have a fixed position and moves if gprs_high or vxrs exist.
59 * Future extensions will be added to _sigregs_ext.
60 */
61struct sigframe
35{ 62{
36 __u8 callee_used_stack[__SIGNAL_FRAMESIZE]; 63 __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
37 struct sigcontext sc; 64 struct sigcontext sc;
38 _sigregs sregs; 65 _sigregs sregs;
39 int signo; 66 int signo;
40 __u8 retcode[S390_SYSCALL_SIZE]; 67 _sigregs_ext sregs_ext;
41} sigframe; 68 __u16 svc_insn; /* Offset of svc_insn is NOT fixed! */
69};
42 70
43typedef struct 71/*
72 * Layout of an rt signal-frame:
73 * -----------------------------------------
74 * | save area (_SIGNAL_FRAMESIZE) |
75 * -----------------------------------------
76 * | svc __NR_rt_sigreturn 2 byte |
77 * -----------------------------------------
78 * | struct siginfo |
79 * -----------------------------------------
80 * | struct ucontext_extended with |
81 * | unsigned long uc_flags |
82 * | struct ucontext *uc_link |
83 * | stack_t uc_stack |
84 * | _sigregs uc_mcontext with |
85 * | _s390_regs_common |
86 * | _s390_fp_regs |
87 * | sigset_t uc_sigmask |
88 * | _sigregs_ext uc_mcontext_ext |
89 * | gprs_high 64 byte (opt) |
90 * | vxrs_low 128 byte (opt) |
91 * | vxrs_high 256 byte (opt)|
92 * | reserved 128 byte (opt) |
93 * -----------------------------------------
94 * Future extensions will be added to _sigregs_ext.
95 */
96struct rt_sigframe
44{ 97{
45 __u8 callee_used_stack[__SIGNAL_FRAMESIZE]; 98 __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
46 __u8 retcode[S390_SYSCALL_SIZE]; 99 __u16 svc_insn;
47 struct siginfo info; 100 struct siginfo info;
48 struct ucontext uc; 101 struct ucontext_extended uc;
49} rt_sigframe; 102};
103
104/* Store registers needed to create the signal frame */
105static void store_sigregs(void)
106{
107 save_access_regs(current->thread.acrs);
108 save_fp_ctl(&current->thread.fp_regs.fpc);
109#ifdef CONFIG_64BIT
110 if (current->thread.vxrs) {
111 int i;
112
113 save_vx_regs(current->thread.vxrs);
114 for (i = 0; i < __NUM_FPRS; i++)
115 current->thread.fp_regs.fprs[i] =
116 *(freg_t *)(current->thread.vxrs + i);
117 } else
118#endif
119 save_fp_regs(current->thread.fp_regs.fprs);
120}
121
122/* Load registers after signal return */
123static void load_sigregs(void)
124{
125 restore_access_regs(current->thread.acrs);
126 /* restore_fp_ctl is done in restore_sigregs */
127#ifdef CONFIG_64BIT
128 if (current->thread.vxrs) {
129 int i;
130
131 for (i = 0; i < __NUM_FPRS; i++)
132 *(freg_t *)(current->thread.vxrs + i) =
133 current->thread.fp_regs.fprs[i];
134 restore_vx_regs(current->thread.vxrs);
135 } else
136#endif
137 restore_fp_regs(current->thread.fp_regs.fprs);
138}
50 139
51/* Returns non-zero on fault. */ 140/* Returns non-zero on fault. */
52static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) 141static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
53{ 142{
54 _sigregs user_sregs; 143 _sigregs user_sregs;
55 144
56 save_access_regs(current->thread.acrs);
57
58 /* Copy a 'clean' PSW mask to the user to avoid leaking 145 /* Copy a 'clean' PSW mask to the user to avoid leaking
59 information about whether PER is currently on. */ 146 information about whether PER is currently on. */
60 user_sregs.regs.psw.mask = PSW_USER_BITS | 147 user_sregs.regs.psw.mask = PSW_USER_BITS |
@@ -63,12 +150,6 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
63 memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs)); 150 memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
64 memcpy(&user_sregs.regs.acrs, current->thread.acrs, 151 memcpy(&user_sregs.regs.acrs, current->thread.acrs,
65 sizeof(user_sregs.regs.acrs)); 152 sizeof(user_sregs.regs.acrs));
66 /*
67 * We have to store the fp registers to current->thread.fp_regs
68 * to merge them with the emulated registers.
69 */
70 save_fp_ctl(&current->thread.fp_regs.fpc);
71 save_fp_regs(current->thread.fp_regs.fprs);
72 memcpy(&user_sregs.fpregs, &current->thread.fp_regs, 153 memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
73 sizeof(user_sregs.fpregs)); 154 sizeof(user_sregs.fpregs));
74 if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs))) 155 if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs)))
@@ -107,20 +188,64 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
107 memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); 188 memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
108 memcpy(&current->thread.acrs, &user_sregs.regs.acrs, 189 memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
109 sizeof(current->thread.acrs)); 190 sizeof(current->thread.acrs));
110 restore_access_regs(current->thread.acrs);
111 191
112 memcpy(&current->thread.fp_regs, &user_sregs.fpregs, 192 memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
113 sizeof(current->thread.fp_regs)); 193 sizeof(current->thread.fp_regs));
114 194
115 restore_fp_regs(current->thread.fp_regs.fprs);
116 clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */ 195 clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */
117 return 0; 196 return 0;
118} 197}
119 198
199/* Returns non-zero on fault. */
200static int save_sigregs_ext(struct pt_regs *regs,
201 _sigregs_ext __user *sregs_ext)
202{
203#ifdef CONFIG_64BIT
204 __u64 vxrs[__NUM_VXRS_LOW];
205 int i;
206
207 /* Save vector registers to signal stack */
208 if (current->thread.vxrs) {
209 for (i = 0; i < __NUM_VXRS_LOW; i++)
210 vxrs[i] = *((__u64 *)(current->thread.vxrs + i) + 1);
211 if (__copy_to_user(&sregs_ext->vxrs_low, vxrs,
212 sizeof(sregs_ext->vxrs_low)) ||
213 __copy_to_user(&sregs_ext->vxrs_high,
214 current->thread.vxrs + __NUM_VXRS_LOW,
215 sizeof(sregs_ext->vxrs_high)))
216 return -EFAULT;
217 }
218#endif
219 return 0;
220}
221
222static int restore_sigregs_ext(struct pt_regs *regs,
223 _sigregs_ext __user *sregs_ext)
224{
225#ifdef CONFIG_64BIT
226 __u64 vxrs[__NUM_VXRS_LOW];
227 int i;
228
229 /* Restore vector registers from signal stack */
230 if (current->thread.vxrs) {
231 if (__copy_from_user(vxrs, &sregs_ext->vxrs_low,
232 sizeof(sregs_ext->vxrs_low)) ||
233 __copy_from_user(current->thread.vxrs + __NUM_VXRS_LOW,
234 &sregs_ext->vxrs_high,
235 sizeof(sregs_ext->vxrs_high)))
236 return -EFAULT;
237 for (i = 0; i < __NUM_VXRS_LOW; i++)
238 *((__u64 *)(current->thread.vxrs + i) + 1) = vxrs[i];
239 }
240#endif
241 return 0;
242}
243
120SYSCALL_DEFINE0(sigreturn) 244SYSCALL_DEFINE0(sigreturn)
121{ 245{
122 struct pt_regs *regs = task_pt_regs(current); 246 struct pt_regs *regs = task_pt_regs(current);
123 sigframe __user *frame = (sigframe __user *)regs->gprs[15]; 247 struct sigframe __user *frame =
248 (struct sigframe __user *) regs->gprs[15];
124 sigset_t set; 249 sigset_t set;
125 250
126 if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE)) 251 if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
@@ -128,6 +253,9 @@ SYSCALL_DEFINE0(sigreturn)
128 set_current_blocked(&set); 253 set_current_blocked(&set);
129 if (restore_sigregs(regs, &frame->sregs)) 254 if (restore_sigregs(regs, &frame->sregs))
130 goto badframe; 255 goto badframe;
256 if (restore_sigregs_ext(regs, &frame->sregs_ext))
257 goto badframe;
258 load_sigregs();
131 return regs->gprs[2]; 259 return regs->gprs[2];
132badframe: 260badframe:
133 force_sig(SIGSEGV, current); 261 force_sig(SIGSEGV, current);
@@ -137,16 +265,20 @@ badframe:
137SYSCALL_DEFINE0(rt_sigreturn) 265SYSCALL_DEFINE0(rt_sigreturn)
138{ 266{
139 struct pt_regs *regs = task_pt_regs(current); 267 struct pt_regs *regs = task_pt_regs(current);
140 rt_sigframe __user *frame = (rt_sigframe __user *)regs->gprs[15]; 268 struct rt_sigframe __user *frame =
269 (struct rt_sigframe __user *)regs->gprs[15];
141 sigset_t set; 270 sigset_t set;
142 271
143 if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set))) 272 if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
144 goto badframe; 273 goto badframe;
145 set_current_blocked(&set); 274 set_current_blocked(&set);
275 if (restore_altstack(&frame->uc.uc_stack))
276 goto badframe;
146 if (restore_sigregs(regs, &frame->uc.uc_mcontext)) 277 if (restore_sigregs(regs, &frame->uc.uc_mcontext))
147 goto badframe; 278 goto badframe;
148 if (restore_altstack(&frame->uc.uc_stack)) 279 if (restore_sigregs_ext(regs, &frame->uc.uc_mcontext_ext))
149 goto badframe; 280 goto badframe;
281 load_sigregs();
150 return regs->gprs[2]; 282 return regs->gprs[2];
151badframe: 283badframe:
152 force_sig(SIGSEGV, current); 284 force_sig(SIGSEGV, current);
@@ -154,11 +286,6 @@ badframe:
154} 286}
155 287
156/* 288/*
157 * Set up a signal frame.
158 */
159
160
161/*
162 * Determine which stack to use.. 289 * Determine which stack to use..
163 */ 290 */
164static inline void __user * 291static inline void __user *
@@ -195,39 +322,63 @@ static inline int map_signal(int sig)
195static int setup_frame(int sig, struct k_sigaction *ka, 322static int setup_frame(int sig, struct k_sigaction *ka,
196 sigset_t *set, struct pt_regs * regs) 323 sigset_t *set, struct pt_regs * regs)
197{ 324{
198 sigframe __user *frame; 325 struct sigframe __user *frame;
199 326 struct sigcontext sc;
200 frame = get_sigframe(ka, regs, sizeof(sigframe)); 327 unsigned long restorer;
328 size_t frame_size;
201 329
330 /*
331 * gprs_high are only present for a 31-bit task running on
332 * a 64-bit kernel (see compat_signal.c) but the space for
333 * gprs_high need to be allocated if vector registers are
334 * included in the signal frame on a 31-bit system.
335 */
336 frame_size = sizeof(*frame) - sizeof(frame->sregs_ext);
337 if (MACHINE_HAS_VX)
338 frame_size += sizeof(frame->sregs_ext);
339 frame = get_sigframe(ka, regs, frame_size);
202 if (frame == (void __user *) -1UL) 340 if (frame == (void __user *) -1UL)
203 return -EFAULT; 341 return -EFAULT;
204 342
205 if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE)) 343 /* Set up backchain. */
344 if (__put_user(regs->gprs[15], (addr_t __user *) frame))
206 return -EFAULT; 345 return -EFAULT;
207 346
347 /* Create struct sigcontext on the signal stack */
348 memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE);
349 sc.sregs = (_sigregs __user __force *) &frame->sregs;
350 if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc)))
351 return -EFAULT;
352
353 /* Store registers needed to create the signal frame */
354 store_sigregs();
355
356 /* Create _sigregs on the signal stack */
208 if (save_sigregs(regs, &frame->sregs)) 357 if (save_sigregs(regs, &frame->sregs))
209 return -EFAULT; 358 return -EFAULT;
210 if (__put_user(&frame->sregs, &frame->sc.sregs)) 359
360 /* Place signal number on stack to allow backtrace from handler. */
361 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
362 return -EFAULT;
363
364 /* Create _sigregs_ext on the signal stack */
365 if (save_sigregs_ext(regs, &frame->sregs_ext))
211 return -EFAULT; 366 return -EFAULT;
212 367
213 /* Set up to return from userspace. If provided, use a stub 368 /* Set up to return from userspace. If provided, use a stub
214 already in userspace. */ 369 already in userspace. */
215 if (ka->sa.sa_flags & SA_RESTORER) { 370 if (ka->sa.sa_flags & SA_RESTORER) {
216 regs->gprs[14] = (unsigned long) 371 restorer = (unsigned long) ka->sa.sa_restorer | PSW_ADDR_AMODE;
217 ka->sa.sa_restorer | PSW_ADDR_AMODE;
218 } else { 372 } else {
219 regs->gprs[14] = (unsigned long) 373 /* Signal frame without vector registers are short ! */
220 frame->retcode | PSW_ADDR_AMODE; 374 __u16 __user *svc = (void *) frame + frame_size - 2;
221 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, 375 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc))
222 (u16 __user *)(frame->retcode)))
223 return -EFAULT; 376 return -EFAULT;
377 restorer = (unsigned long) svc | PSW_ADDR_AMODE;
224 } 378 }
225 379
226 /* Set up backchain. */
227 if (__put_user(regs->gprs[15], (addr_t __user *) frame))
228 return -EFAULT;
229
230 /* Set up registers for signal handler */ 380 /* Set up registers for signal handler */
381 regs->gprs[14] = restorer;
231 regs->gprs[15] = (unsigned long) frame; 382 regs->gprs[15] = (unsigned long) frame;
232 /* Force default amode and default user address space control. */ 383 /* Force default amode and default user address space control. */
233 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | 384 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
@@ -247,54 +398,69 @@ static int setup_frame(int sig, struct k_sigaction *ka,
247 regs->gprs[5] = regs->int_parm_long; 398 regs->gprs[5] = regs->int_parm_long;
248 regs->gprs[6] = task_thread_info(current)->last_break; 399 regs->gprs[6] = task_thread_info(current)->last_break;
249 } 400 }
250
251 /* Place signal number on stack to allow backtrace from handler. */
252 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
253 return -EFAULT;
254 return 0; 401 return 0;
255} 402}
256 403
257static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, 404static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
258 struct pt_regs *regs) 405 struct pt_regs *regs)
259{ 406{
260 int err = 0; 407 struct rt_sigframe __user *frame;
261 rt_sigframe __user *frame; 408 unsigned long uc_flags, restorer;
262 409 size_t frame_size;
263 frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe));
264 410
411 frame_size = sizeof(struct rt_sigframe) - sizeof(_sigregs_ext);
412 /*
413 * gprs_high are only present for a 31-bit task running on
414 * a 64-bit kernel (see compat_signal.c) but the space for
415 * gprs_high need to be allocated if vector registers are
416 * included in the signal frame on a 31-bit system.
417 */
418 uc_flags = 0;
419#ifdef CONFIG_64BIT
420 if (MACHINE_HAS_VX) {
421 frame_size += sizeof(_sigregs_ext);
422 if (current->thread.vxrs)
423 uc_flags |= UC_VXRS;
424 }
425#endif
426 frame = get_sigframe(&ksig->ka, regs, frame_size);
265 if (frame == (void __user *) -1UL) 427 if (frame == (void __user *) -1UL)
266 return -EFAULT; 428 return -EFAULT;
267 429
268 if (copy_siginfo_to_user(&frame->info, &ksig->info)) 430 /* Set up backchain. */
269 return -EFAULT; 431 if (__put_user(regs->gprs[15], (addr_t __user *) frame))
270
271 /* Create the ucontext. */
272 err |= __put_user(0, &frame->uc.uc_flags);
273 err |= __put_user(NULL, &frame->uc.uc_link);
274 err |= __save_altstack(&frame->uc.uc_stack, regs->gprs[15]);
275 err |= save_sigregs(regs, &frame->uc.uc_mcontext);
276 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
277 if (err)
278 return -EFAULT; 432 return -EFAULT;
279 433
280 /* Set up to return from userspace. If provided, use a stub 434 /* Set up to return from userspace. If provided, use a stub
281 already in userspace. */ 435 already in userspace. */
282 if (ksig->ka.sa.sa_flags & SA_RESTORER) { 436 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
283 regs->gprs[14] = (unsigned long) 437 restorer = (unsigned long)
284 ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE; 438 ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE;
285 } else { 439 } else {
286 regs->gprs[14] = (unsigned long) 440 __u16 __user *svc = &frame->svc_insn;
287 frame->retcode | PSW_ADDR_AMODE; 441 if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc))
288 if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
289 (u16 __user *)(frame->retcode)))
290 return -EFAULT; 442 return -EFAULT;
443 restorer = (unsigned long) svc | PSW_ADDR_AMODE;
291 } 444 }
292 445
293 /* Set up backchain. */ 446 /* Create siginfo on the signal stack */
294 if (__put_user(regs->gprs[15], (addr_t __user *) frame)) 447 if (copy_siginfo_to_user(&frame->info, &ksig->info))
448 return -EFAULT;
449
450 /* Store registers needed to create the signal frame */
451 store_sigregs();
452
453 /* Create ucontext on the signal stack. */
454 if (__put_user(uc_flags, &frame->uc.uc_flags) ||
455 __put_user(NULL, &frame->uc.uc_link) ||
456 __save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
457 save_sigregs(regs, &frame->uc.uc_mcontext) ||
458 __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) ||
459 save_sigregs_ext(regs, &frame->uc.uc_mcontext_ext))
295 return -EFAULT; 460 return -EFAULT;
296 461
297 /* Set up registers for signal handler */ 462 /* Set up registers for signal handler */
463 regs->gprs[14] = restorer;
298 regs->gprs[15] = (unsigned long) frame; 464 regs->gprs[15] = (unsigned long) frame;
299 /* Force default amode and default user address space control. */ 465 /* Force default amode and default user address space control. */
300 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | 466 regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index bba0e2469254..13cae5b152d7 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -179,6 +179,9 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
179 goto out; 179 goto out;
180 } 180 }
181#else 181#else
182 if (MACHINE_HAS_VX)
183 lc->vector_save_area_addr =
184 (unsigned long) &lc->vector_save_area;
182 if (vdso_alloc_per_cpu(lc)) 185 if (vdso_alloc_per_cpu(lc))
183 goto out; 186 goto out;
184#endif 187#endif
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index e3e06a4fdfce..9ff5ecba26ab 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -18,6 +18,8 @@
18#include <linux/ptrace.h> 18#include <linux/ptrace.h>
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/mm.h> 20#include <linux/mm.h>
21#include <linux/slab.h>
22#include <asm/switch_to.h>
21#include "entry.h" 23#include "entry.h"
22 24
23int show_unhandled_signals = 1; 25int show_unhandled_signals = 1;
@@ -303,6 +305,74 @@ DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
303 "specification exception"); 305 "specification exception");
304#endif 306#endif
305 307
308#ifdef CONFIG_64BIT
309int alloc_vector_registers(struct task_struct *tsk)
310{
311 __vector128 *vxrs;
312 int i;
313
314 /* Allocate vector register save area. */
315 vxrs = kzalloc(sizeof(__vector128) * __NUM_VXRS,
316 GFP_KERNEL|__GFP_REPEAT);
317 if (!vxrs)
318 return -ENOMEM;
319 preempt_disable();
320 if (tsk == current)
321 save_fp_regs(tsk->thread.fp_regs.fprs);
322 /* Copy the 16 floating point registers */
323 for (i = 0; i < 16; i++)
324 *(freg_t *) &vxrs[i] = tsk->thread.fp_regs.fprs[i];
325 tsk->thread.vxrs = vxrs;
326 if (tsk == current) {
327 __ctl_set_bit(0, 17);
328 restore_vx_regs(vxrs);
329 }
330 preempt_enable();
331 return 0;
332}
333
334void vector_exception(struct pt_regs *regs)
335{
336 int si_code, vic;
337
338 if (!MACHINE_HAS_VX) {
339 do_trap(regs, SIGILL, ILL_ILLOPN, "illegal operation");
340 return;
341 }
342
343 /* get vector interrupt code from fpc */
344 asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
345 vic = (current->thread.fp_regs.fpc & 0xf00) >> 8;
346 switch (vic) {
347 case 1: /* invalid vector operation */
348 si_code = FPE_FLTINV;
349 break;
350 case 2: /* division by zero */
351 si_code = FPE_FLTDIV;
352 break;
353 case 3: /* overflow */
354 si_code = FPE_FLTOVF;
355 break;
356 case 4: /* underflow */
357 si_code = FPE_FLTUND;
358 break;
359 case 5: /* inexact */
360 si_code = FPE_FLTRES;
361 break;
362 default: /* unknown cause */
363 si_code = 0;
364 }
365 do_trap(regs, SIGFPE, si_code, "vector exception");
366}
367
368static int __init disable_vector_extension(char *str)
369{
370 S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX;
371 return 1;
372}
373__setup("novx", disable_vector_extension);
374#endif
375
306void data_exception(struct pt_regs *regs) 376void data_exception(struct pt_regs *regs)
307{ 377{
308 __u16 __user *location; 378 __u16 __user *location;
@@ -368,6 +438,18 @@ void data_exception(struct pt_regs *regs)
368 } 438 }
369 } 439 }
370#endif 440#endif
441#ifdef CONFIG_64BIT
442 /* Check for vector register enablement */
443 if (MACHINE_HAS_VX && !current->thread.vxrs &&
444 (current->thread.fp_regs.fpc & FPC_DXC_MASK) == 0xfe00) {
445 alloc_vector_registers(current);
446 /* Vector data exception is suppressing, rewind psw. */
447 regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
448 clear_pt_regs_flag(regs, PIF_PER_TRAP);
449 return;
450 }
451#endif
452
371 if (current->thread.fp_regs.fpc & FPC_DXC_MASK) 453 if (current->thread.fp_regs.fpc & FPC_DXC_MASK)
372 signal = SIGFPE; 454 signal = SIGFPE;
373 else 455 else