aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/elf.h1
-rw-r--r--arch/s390/include/asm/lowcore.h6
-rw-r--r--arch/s390/include/asm/processor.h6
-rw-r--r--arch/s390/include/asm/ptrace.h8
-rw-r--r--arch/s390/include/asm/setup.h3
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/dis.c12
-rw-r--r--arch/s390/kernel/early.c3
-rw-r--r--arch/s390/kernel/entry64.S12
-rw-r--r--arch/s390/kernel/processor.c6
-rw-r--r--arch/s390/kernel/ptrace.c69
-rw-r--r--arch/s390/kernel/setup.c6
-rw-r--r--arch/s390/kernel/traps.c37
-rw-r--r--include/linux/elf.h1
14 files changed, 151 insertions, 21 deletions
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 9b94a160fe7f..db57594e94b0 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -101,6 +101,7 @@
101#define HWCAP_S390_HPAGE 128 101#define HWCAP_S390_HPAGE 128
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 105
105/* 106/*
106 * These are used to set parameters in the core dumps. 107 * 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 aab5555bbbda..bbf8141408cd 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -329,9 +329,13 @@ struct _lowcore {
329 __u8 pad_0x1338[0x1340-0x1338]; /* 0x1338 */ 329 __u8 pad_0x1338[0x1340-0x1338]; /* 0x1338 */
330 __u32 access_regs_save_area[16]; /* 0x1340 */ 330 __u32 access_regs_save_area[16]; /* 0x1340 */
331 __u64 cregs_save_area[16]; /* 0x1380 */ 331 __u64 cregs_save_area[16]; /* 0x1380 */
332 __u8 pad_0x1400[0x1800-0x1400]; /* 0x1400 */
333
334 /* Transaction abort diagnostic block */
335 __u8 pgm_tdb[256]; /* 0x1800 */
332 336
333 /* align to the top of the prefix area */ 337 /* align to the top of the prefix area */
334 __u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */ 338 __u8 pad_0x1900[0x2000-0x1900]; /* 0x1900 */
335} __packed; 339} __packed;
336 340
337#endif /* CONFIG_32BIT */ 341#endif /* CONFIG_32BIT */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 0fff583d2c7c..46fe1fbf91c5 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -76,14 +76,20 @@ struct thread_struct {
76 unsigned long gmap_addr; /* address of last gmap fault. */ 76 unsigned long gmap_addr; /* address of last gmap fault. */
77 struct per_regs per_user; /* User specified PER registers */ 77 struct per_regs per_user; /* User specified PER registers */
78 struct per_event per_event; /* Cause of the last PER trap */ 78 struct per_event per_event; /* Cause of the last PER trap */
79 unsigned long per_flags; /* Flags to control debug behavior */
79 /* pfault_wait is used to block the process on a pfault event */ 80 /* pfault_wait is used to block the process on a pfault event */
80 unsigned long pfault_wait; 81 unsigned long pfault_wait;
81 struct list_head list; 82 struct list_head list;
82 /* cpu runtime instrumentation */ 83 /* cpu runtime instrumentation */
83 struct runtime_instr_cb *ri_cb; 84 struct runtime_instr_cb *ri_cb;
84 int ri_signum; 85 int ri_signum;
86#ifdef CONFIG_64BIT
87 unsigned char trap_tdb[256]; /* Transaction abort diagnose block */
88#endif
85}; 89};
86 90
91#define PER_FLAG_NO_TE 1UL /* Flag to disable transactions. */
92
87typedef struct thread_struct thread_struct; 93typedef struct thread_struct thread_struct;
88 94
89/* 95/*
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 5c32bae6b760..ce20a53afe91 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -361,17 +361,19 @@ struct per_struct_kernel {
361 unsigned char access_id; /* PER trap access identification */ 361 unsigned char access_id; /* PER trap access identification */
362}; 362};
363 363
364#define PER_EVENT_MASK 0xE9000000UL 364#define PER_EVENT_MASK 0xEB000000UL
365 365
366#define PER_EVENT_BRANCH 0x80000000UL 366#define PER_EVENT_BRANCH 0x80000000UL
367#define PER_EVENT_IFETCH 0x40000000UL 367#define PER_EVENT_IFETCH 0x40000000UL
368#define PER_EVENT_STORE 0x20000000UL 368#define PER_EVENT_STORE 0x20000000UL
369#define PER_EVENT_STORE_REAL 0x08000000UL 369#define PER_EVENT_STORE_REAL 0x08000000UL
370#define PER_EVENT_TRANSACTION_END 0x02000000UL
370#define PER_EVENT_NULLIFICATION 0x01000000UL 371#define PER_EVENT_NULLIFICATION 0x01000000UL
371 372
372#define PER_CONTROL_MASK 0x00a00000UL 373#define PER_CONTROL_MASK 0x00e00000UL
373 374
374#define PER_CONTROL_BRANCH_ADDRESS 0x00800000UL 375#define PER_CONTROL_BRANCH_ADDRESS 0x00800000UL
376#define PER_CONTROL_SUSPENSION 0x00400000UL
375#define PER_CONTROL_ALTERATION 0x00200000UL 377#define PER_CONTROL_ALTERATION 0x00200000UL
376 378
377#endif 379#endif
@@ -485,6 +487,8 @@ typedef struct
485#define PTRACE_GET_LAST_BREAK 0x5006 487#define PTRACE_GET_LAST_BREAK 0x5006
486#define PTRACE_PEEK_SYSTEM_CALL 0x5007 488#define PTRACE_PEEK_SYSTEM_CALL 0x5007
487#define PTRACE_POKE_SYSTEM_CALL 0x5008 489#define PTRACE_POKE_SYSTEM_CALL 0x5008
490#define PTRACE_ENABLE_TE 0x5009
491#define PTRACE_DISABLE_TE 0x5010
488 492
489/* 493/*
490 * PT_PROT definition is loosely based on hppa bsd definition in 494 * PT_PROT definition is loosely based on hppa bsd definition in
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index e6859d16ee2d..908f68871393 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -80,6 +80,7 @@ extern unsigned int addressing_mode;
80#define MACHINE_FLAG_LPAR (1UL << 12) 80#define MACHINE_FLAG_LPAR (1UL << 12)
81#define MACHINE_FLAG_SPP (1UL << 13) 81#define MACHINE_FLAG_SPP (1UL << 13)
82#define MACHINE_FLAG_TOPOLOGY (1UL << 14) 82#define MACHINE_FLAG_TOPOLOGY (1UL << 14)
83#define MACHINE_FLAG_TE (1UL << 15)
83 84
84#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) 85#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
85#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) 86#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -98,6 +99,7 @@ extern unsigned int addressing_mode;
98#define MACHINE_HAS_PFMF (0) 99#define MACHINE_HAS_PFMF (0)
99#define MACHINE_HAS_SPP (0) 100#define MACHINE_HAS_SPP (0)
100#define MACHINE_HAS_TOPOLOGY (0) 101#define MACHINE_HAS_TOPOLOGY (0)
102#define MACHINE_HAS_TE (0)
101#else /* CONFIG_64BIT */ 103#else /* CONFIG_64BIT */
102#define MACHINE_HAS_IEEE (1) 104#define MACHINE_HAS_IEEE (1)
103#define MACHINE_HAS_CSP (1) 105#define MACHINE_HAS_CSP (1)
@@ -109,6 +111,7 @@ extern unsigned int addressing_mode;
109#define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) 111#define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
110#define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) 112#define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
111#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) 113#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
114#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
112#endif /* CONFIG_64BIT */ 115#endif /* CONFIG_64BIT */
113 116
114#define ZFCPDUMP_HSA_SIZE (32UL<<20) 117#define ZFCPDUMP_HSA_SIZE (32UL<<20)
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 45ef1a7b08f9..fface87056eb 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -157,6 +157,8 @@ int main(void)
157 DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr)); 157 DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr));
158 DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); 158 DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
159 DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap)); 159 DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap));
160 DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb));
161 DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb));
160 DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); 162 DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce));
161#endif /* CONFIG_32BIT */ 163#endif /* CONFIG_32BIT */
162 return 0; 164 return 0;
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index 4bc67db63522..7b6ad271155d 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -317,6 +317,9 @@ enum {
317 LONG_INSN_RISBLG, 317 LONG_INSN_RISBLG,
318 LONG_INSN_RINEXT, 318 LONG_INSN_RINEXT,
319 LONG_INSN_RIEMIT, 319 LONG_INSN_RIEMIT,
320 LONG_INSN_TABORT,
321 LONG_INSN_TBEGIN,
322 LONG_INSN_TBEGINC,
320}; 323};
321 324
322static char *long_insn_name[] = { 325static char *long_insn_name[] = {
@@ -334,6 +337,9 @@ static char *long_insn_name[] = {
334 [LONG_INSN_RISBLG] = "risblk", 337 [LONG_INSN_RISBLG] = "risblk",
335 [LONG_INSN_RINEXT] = "rinext", 338 [LONG_INSN_RINEXT] = "rinext",
336 [LONG_INSN_RIEMIT] = "riemit", 339 [LONG_INSN_RIEMIT] = "riemit",
340 [LONG_INSN_TABORT] = "tabort",
341 [LONG_INSN_TBEGIN] = "tbegin",
342 [LONG_INSN_TBEGINC] = "tbeginc",
337}; 343};
338 344
339static struct insn opcode[] = { 345static struct insn opcode[] = {
@@ -609,6 +615,9 @@ static struct insn opcode_b2[] = {
609 { "lpswe", 0xb2, INSTR_S_RD }, 615 { "lpswe", 0xb2, INSTR_S_RD },
610 { "srnmt", 0xb9, INSTR_S_RD }, 616 { "srnmt", 0xb9, INSTR_S_RD },
611 { "lfas", 0xbd, INSTR_S_RD }, 617 { "lfas", 0xbd, INSTR_S_RD },
618 { "etndg", 0xec, INSTR_RRE_R0 },
619 { { 0, LONG_INSN_TABORT }, 0xfc, INSTR_S_RD },
620 { "tend", 0xf8, INSTR_S_RD },
612#endif 621#endif
613 { "stidp", 0x02, INSTR_S_RD }, 622 { "stidp", 0x02, INSTR_S_RD },
614 { "sck", 0x04, INSTR_S_RD }, 623 { "sck", 0x04, INSTR_S_RD },
@@ -1165,6 +1174,7 @@ static struct insn opcode_e3[] = {
1165 { "stfh", 0xcb, INSTR_RXY_RRRD }, 1174 { "stfh", 0xcb, INSTR_RXY_RRRD },
1166 { "chf", 0xcd, INSTR_RXY_RRRD }, 1175 { "chf", 0xcd, INSTR_RXY_RRRD },
1167 { "clhf", 0xcf, INSTR_RXY_RRRD }, 1176 { "clhf", 0xcf, INSTR_RXY_RRRD },
1177 { "ntstg", 0x25, INSTR_RXY_RRRD },
1168#endif 1178#endif
1169 { "lrv", 0x1e, INSTR_RXY_RRRD }, 1179 { "lrv", 0x1e, INSTR_RXY_RRRD },
1170 { "lrvh", 0x1f, INSTR_RXY_RRRD }, 1180 { "lrvh", 0x1f, INSTR_RXY_RRRD },
@@ -1188,6 +1198,8 @@ static struct insn opcode_e5[] = {
1188 { "mvhhi", 0x44, INSTR_SIL_RDI }, 1198 { "mvhhi", 0x44, INSTR_SIL_RDI },
1189 { "mvhi", 0x4c, INSTR_SIL_RDI }, 1199 { "mvhi", 0x4c, INSTR_SIL_RDI },
1190 { "mvghi", 0x48, INSTR_SIL_RDI }, 1200 { "mvghi", 0x48, INSTR_SIL_RDI },
1201 { { 0, LONG_INSN_TBEGIN }, 0x60, INSTR_SIL_RDU },
1202 { { 0, LONG_INSN_TBEGINC }, 0x61, INSTR_SIL_RDU },
1191#endif 1203#endif
1192 { "lasp", 0x00, INSTR_SSE_RDRD }, 1204 { "lasp", 0x00, INSTR_SSE_RDRD },
1193 { "tprot", 0x01, INSTR_SSE_RDRD }, 1205 { "tprot", 0x01, INSTR_SSE_RDRD },
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index e48407962b0f..1345ba452c83 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -370,6 +370,8 @@ static __init void detect_machine_facilities(void)
370 S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; 370 S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
371 if (test_facility(40)) 371 if (test_facility(40))
372 S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; 372 S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
373 if (test_facility(50) && test_facility(73))
374 S390_lowcore.machine_flags |= MACHINE_FLAG_TE;
373#endif 375#endif
374} 376}
375 377
@@ -439,7 +441,6 @@ static void __init setup_boot_command_line(void)
439 append_to_cmdline(append_ipl_scpdata); 441 append_to_cmdline(append_ipl_scpdata);
440} 442}
441 443
442
443/* 444/*
444 * Save ipl parameters, clear bss memory, initialize storage keys 445 * Save ipl parameters, clear bss memory, initialize storage keys
445 * and create a kernel NSS at startup if the SAVESYS= parm is defined 446 * and create a kernel NSS at startup if the SAVESYS= parm is defined
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 349b7eeb348a..95e9d93d4f41 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -412,6 +412,11 @@ ENTRY(pgm_check_handler)
4121: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER 4121: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER
413 LAST_BREAK %r14 413 LAST_BREAK %r14
414 lg %r15,__LC_KERNEL_STACK 414 lg %r15,__LC_KERNEL_STACK
415 lg %r14,__TI_task(%r12)
416 lghi %r13,__LC_PGM_TDB
417 tm __LC_PGM_ILC+2,0x02 # check for transaction abort
418 jz 2f
419 mvc __THREAD_trap_tdb(256,%r14),0(%r13)
4152: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 4202: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
416 la %r11,STACK_FRAME_OVERHEAD(%r15) 421 la %r11,STACK_FRAME_OVERHEAD(%r15)
417 stmg %r0,%r7,__PT_R0(%r11) 422 stmg %r0,%r7,__PT_R0(%r11)
@@ -422,13 +427,12 @@ ENTRY(pgm_check_handler)
422 stg %r10,__PT_ARGS(%r11) 427 stg %r10,__PT_ARGS(%r11)
423 tm __LC_PGM_ILC+3,0x80 # check for per exception 428 tm __LC_PGM_ILC+3,0x80 # check for per exception
424 jz 0f 429 jz 0f
425 lg %r1,__TI_task(%r12)
426 tmhh %r8,0x0001 # kernel per event ? 430 tmhh %r8,0x0001 # kernel per event ?
427 jz pgm_kprobe 431 jz pgm_kprobe
428 oi __TI_flags+7(%r12),_TIF_PER_TRAP 432 oi __TI_flags+7(%r12),_TIF_PER_TRAP
429 mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS 433 mvc __THREAD_per_address(8,%r14),__LC_PER_ADDRESS
430 mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE 434 mvc __THREAD_per_cause(2,%r14),__LC_PER_CAUSE
431 mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID 435 mvc __THREAD_per_paid(1,%r14),__LC_PER_PAID
4320: REENABLE_IRQS 4360: REENABLE_IRQS
433 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 437 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
434 larl %r1,pgm_check_table 438 larl %r1,pgm_check_table
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 572d4c9cb33b..22bf8f0ee093 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -39,9 +39,9 @@ void __cpuinit cpu_init(void)
39 */ 39 */
40static int show_cpuinfo(struct seq_file *m, void *v) 40static int show_cpuinfo(struct seq_file *m, void *v)
41{ 41{
42 static const char *hwcap_str[10] = { 42 static const char *hwcap_str[11] = {
43 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", 43 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
44 "edat", "etf3eh", "highgprs" 44 "edat", "etf3eh", "highgprs", "te"
45 }; 45 };
46 unsigned long n = (unsigned long) v - 1; 46 unsigned long n = (unsigned long) v - 1;
47 int i; 47 int i;
@@ -54,7 +54,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
54 num_online_cpus(), loops_per_jiffy/(500000/HZ), 54 num_online_cpus(), loops_per_jiffy/(500000/HZ),
55 (loops_per_jiffy/(5000/HZ))%100); 55 (loops_per_jiffy/(5000/HZ))%100);
56 seq_puts(m, "features\t: "); 56 seq_puts(m, "features\t: ");
57 for (i = 0; i < 10; i++) 57 for (i = 0; i < 11; i++)
58 if (hwcap_str[i] && (elf_hwcap & (1UL << i))) 58 if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
59 seq_printf(m, "%s ", hwcap_str[i]); 59 seq_printf(m, "%s ", hwcap_str[i]);
60 seq_puts(m, "\n"); 60 seq_puts(m, "\n");
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index e4be113fbac6..b817cc5e49ae 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -42,6 +42,7 @@ enum s390_regset {
42 REGSET_GENERAL, 42 REGSET_GENERAL,
43 REGSET_FP, 43 REGSET_FP,
44 REGSET_LAST_BREAK, 44 REGSET_LAST_BREAK,
45 REGSET_TDB,
45 REGSET_SYSTEM_CALL, 46 REGSET_SYSTEM_CALL,
46 REGSET_GENERAL_EXTENDED, 47 REGSET_GENERAL_EXTENDED,
47}; 48};
@@ -52,6 +53,21 @@ void update_per_regs(struct task_struct *task)
52 struct thread_struct *thread = &task->thread; 53 struct thread_struct *thread = &task->thread;
53 struct per_regs old, new; 54 struct per_regs old, new;
54 55
56 /* Take care of the enable/disable of transactional execution. */
57 if (MACHINE_HAS_TE) {
58 unsigned long cr0, cr0_new;
59
60 __ctl_store(cr0, 0, 0);
61 /* set or clear transaction execution bits 8 and 9. */
62 if (task->thread.per_flags & PER_FLAG_NO_TE)
63 cr0_new = cr0 & ~(3UL << 54);
64 else
65 cr0_new = cr0 | (3UL << 54);
66 /* Only load control register 0 if necessary. */
67 if (cr0 != cr0_new)
68 __ctl_load(cr0_new, 0, 0);
69 }
70
55 /* Copy user specified PER registers */ 71 /* Copy user specified PER registers */
56 new.control = thread->per_user.control; 72 new.control = thread->per_user.control;
57 new.start = thread->per_user.start; 73 new.start = thread->per_user.start;
@@ -60,6 +76,10 @@ void update_per_regs(struct task_struct *task)
60 /* merge TIF_SINGLE_STEP into user specified PER registers. */ 76 /* merge TIF_SINGLE_STEP into user specified PER registers. */
61 if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) { 77 if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
62 new.control |= PER_EVENT_IFETCH; 78 new.control |= PER_EVENT_IFETCH;
79#ifdef CONFIG_64BIT
80 new.control |= PER_CONTROL_SUSPENSION;
81 new.control |= PER_EVENT_TRANSACTION_END;
82#endif
63 new.start = 0; 83 new.start = 0;
64 new.end = PSW_ADDR_INSN; 84 new.end = PSW_ADDR_INSN;
65 } 85 }
@@ -100,6 +120,7 @@ void ptrace_disable(struct task_struct *task)
100 memset(&task->thread.per_event, 0, sizeof(task->thread.per_event)); 120 memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));
101 clear_tsk_thread_flag(task, TIF_SINGLE_STEP); 121 clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
102 clear_tsk_thread_flag(task, TIF_PER_TRAP); 122 clear_tsk_thread_flag(task, TIF_PER_TRAP);
123 task->thread.per_flags = 0;
103} 124}
104 125
105#ifndef CONFIG_64BIT 126#ifndef CONFIG_64BIT
@@ -416,6 +437,16 @@ long arch_ptrace(struct task_struct *child, long request,
416 put_user(task_thread_info(child)->last_break, 437 put_user(task_thread_info(child)->last_break,
417 (unsigned long __user *) data); 438 (unsigned long __user *) data);
418 return 0; 439 return 0;
440 case PTRACE_ENABLE_TE:
441 if (!MACHINE_HAS_TE)
442 return -EIO;
443 child->thread.per_flags &= ~PER_FLAG_NO_TE;
444 return 0;
445 case PTRACE_DISABLE_TE:
446 if (!MACHINE_HAS_TE)
447 return -EIO;
448 child->thread.per_flags |= PER_FLAG_NO_TE;
449 return 0;
419 default: 450 default:
420 /* Removing high order bit from addr (only for 31 bit). */ 451 /* Removing high order bit from addr (only for 31 bit). */
421 addr &= PSW_ADDR_INSN; 452 addr &= PSW_ADDR_INSN;
@@ -903,6 +934,28 @@ static int s390_last_break_set(struct task_struct *target,
903 return 0; 934 return 0;
904} 935}
905 936
937static int s390_tdb_get(struct task_struct *target,
938 const struct user_regset *regset,
939 unsigned int pos, unsigned int count,
940 void *kbuf, void __user *ubuf)
941{
942 struct pt_regs *regs = task_pt_regs(target);
943 unsigned char *data;
944
945 if (!(regs->int_code & 0x200))
946 return -ENODATA;
947 data = target->thread.trap_tdb;
948 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, data, 0, 256);
949}
950
951static int s390_tdb_set(struct task_struct *target,
952 const struct user_regset *regset,
953 unsigned int pos, unsigned int count,
954 const void *kbuf, const void __user *ubuf)
955{
956 return 0;
957}
958
906#endif 959#endif
907 960
908static int s390_system_call_get(struct task_struct *target, 961static int s390_system_call_get(struct task_struct *target,
@@ -951,6 +1004,14 @@ static const struct user_regset s390_regsets[] = {
951 .get = s390_last_break_get, 1004 .get = s390_last_break_get,
952 .set = s390_last_break_set, 1005 .set = s390_last_break_set,
953 }, 1006 },
1007 [REGSET_TDB] = {
1008 .core_note_type = NT_S390_TDB,
1009 .n = 1,
1010 .size = 256,
1011 .align = 1,
1012 .get = s390_tdb_get,
1013 .set = s390_tdb_set,
1014 },
954#endif 1015#endif
955 [REGSET_SYSTEM_CALL] = { 1016 [REGSET_SYSTEM_CALL] = {
956 .core_note_type = NT_S390_SYSTEM_CALL, 1017 .core_note_type = NT_S390_SYSTEM_CALL,
@@ -1148,6 +1209,14 @@ static const struct user_regset s390_compat_regsets[] = {
1148 .get = s390_compat_last_break_get, 1209 .get = s390_compat_last_break_get,
1149 .set = s390_compat_last_break_set, 1210 .set = s390_compat_last_break_set,
1150 }, 1211 },
1212 [REGSET_TDB] = {
1213 .core_note_type = NT_S390_TDB,
1214 .n = 1,
1215 .size = 256,
1216 .align = 1,
1217 .get = s390_tdb_get,
1218 .set = s390_tdb_set,
1219 },
1151 [REGSET_SYSTEM_CALL] = { 1220 [REGSET_SYSTEM_CALL] = {
1152 .core_note_type = NT_S390_SYSTEM_CALL, 1221 .core_note_type = NT_S390_SYSTEM_CALL,
1153 .n = 1, 1222 .n = 1,
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 40b57693de38..7b59fff85f2f 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -980,6 +980,12 @@ static void __init setup_hwcaps(void)
980 * HWCAP_S390_HIGH_GPRS is bit 9. 980 * HWCAP_S390_HIGH_GPRS is bit 9.
981 */ 981 */
982 elf_hwcap |= HWCAP_S390_HIGH_GPRS; 982 elf_hwcap |= HWCAP_S390_HIGH_GPRS;
983
984 /*
985 * Transactional execution support HWCAP_S390_TE is bit 10.
986 */
987 if (test_facility(50) && test_facility(73))
988 elf_hwcap |= HWCAP_S390_TE;
983#endif 989#endif
984 990
985 get_cpu_id(&cpu_id); 991 get_cpu_id(&cpu_id);
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 01775c04a90e..29af52628e8b 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -57,6 +57,23 @@ static int kstack_depth_to_print = 12;
57static int kstack_depth_to_print = 20; 57static int kstack_depth_to_print = 20;
58#endif /* CONFIG_64BIT */ 58#endif /* CONFIG_64BIT */
59 59
60static inline void __user *get_trap_ip(struct pt_regs *regs)
61{
62#ifdef CONFIG_64BIT
63 unsigned long address;
64
65 if (regs->int_code & 0x200)
66 address = *(unsigned long *)(current->thread.trap_tdb + 24);
67 else
68 address = regs->psw.addr;
69 return (void __user *)
70 ((address - (regs->int_code >> 16)) & PSW_ADDR_INSN);
71#else
72 return (void __user *)
73 ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN);
74#endif
75}
76
60/* 77/*
61 * For show_trace we have tree different stack to consider: 78 * For show_trace we have tree different stack to consider:
62 * - the panic stack which is used if the kernel stack has overflown 79 * - the panic stack which is used if the kernel stack has overflown
@@ -285,12 +302,6 @@ int is_valid_bugaddr(unsigned long addr)
285 return 1; 302 return 1;
286} 303}
287 304
288static inline void __user *get_psw_address(struct pt_regs *regs)
289{
290 return (void __user *)
291 ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN);
292}
293
294static void __kprobes do_trap(struct pt_regs *regs, 305static void __kprobes do_trap(struct pt_regs *regs,
295 int si_signo, int si_code, char *str) 306 int si_signo, int si_code, char *str)
296{ 307{
@@ -304,7 +315,7 @@ static void __kprobes do_trap(struct pt_regs *regs,
304 info.si_signo = si_signo; 315 info.si_signo = si_signo;
305 info.si_errno = 0; 316 info.si_errno = 0;
306 info.si_code = si_code; 317 info.si_code = si_code;
307 info.si_addr = get_psw_address(regs); 318 info.si_addr = get_trap_ip(regs);
308 force_sig_info(si_signo, &info, current); 319 force_sig_info(si_signo, &info, current);
309 report_user_fault(regs, si_signo); 320 report_user_fault(regs, si_signo);
310 } else { 321 } else {
@@ -381,6 +392,11 @@ DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN,
381DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, 392DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN,
382 "translation exception") 393 "translation exception")
383 394
395#ifdef CONFIG_64BIT
396DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN,
397 "transaction constraint exception")
398#endif
399
384static inline void do_fp_trap(struct pt_regs *regs, int fpc) 400static inline void do_fp_trap(struct pt_regs *regs, int fpc)
385{ 401{
386 int si_code = 0; 402 int si_code = 0;
@@ -408,7 +424,7 @@ static void __kprobes illegal_op(struct pt_regs *regs)
408 __u16 __user *location; 424 __u16 __user *location;
409 int signal = 0; 425 int signal = 0;
410 426
411 location = get_psw_address(regs); 427 location = get_trap_ip(regs);
412 428
413 if (user_mode(regs)) { 429 if (user_mode(regs)) {
414 if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) 430 if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
@@ -476,7 +492,7 @@ void specification_exception(struct pt_regs *regs)
476 __u16 __user *location = NULL; 492 __u16 __user *location = NULL;
477 int signal = 0; 493 int signal = 0;
478 494
479 location = (__u16 __user *) get_psw_address(regs); 495 location = (__u16 __user *) get_trap_ip(regs);
480 496
481 if (user_mode(regs)) { 497 if (user_mode(regs)) {
482 get_user(*((__u16 *) opcode), location); 498 get_user(*((__u16 *) opcode), location);
@@ -525,7 +541,7 @@ static void data_exception(struct pt_regs *regs)
525 __u16 __user *location; 541 __u16 __user *location;
526 int signal = 0; 542 int signal = 0;
527 543
528 location = get_psw_address(regs); 544 location = get_trap_ip(regs);
529 545
530 if (MACHINE_HAS_IEEE) 546 if (MACHINE_HAS_IEEE)
531 asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); 547 asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
@@ -641,6 +657,7 @@ void __init trap_init(void)
641 pgm_check_table[0x12] = &translation_exception; 657 pgm_check_table[0x12] = &translation_exception;
642 pgm_check_table[0x13] = &special_op_exception; 658 pgm_check_table[0x13] = &special_op_exception;
643#ifdef CONFIG_64BIT 659#ifdef CONFIG_64BIT
660 pgm_check_table[0x18] = &transaction_exception;
644 pgm_check_table[0x38] = &do_asce_exception; 661 pgm_check_table[0x38] = &do_asce_exception;
645 pgm_check_table[0x39] = &do_dat_exception; 662 pgm_check_table[0x39] = &do_dat_exception;
646 pgm_check_table[0x3A] = &do_dat_exception; 663 pgm_check_table[0x3A] = &do_dat_exception;
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 999b4f52e8e5..f930b1a390ab 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -387,6 +387,7 @@ typedef struct elf64_shdr {
387#define NT_S390_PREFIX 0x305 /* s390 prefix register */ 387#define NT_S390_PREFIX 0x305 /* s390 prefix register */
388#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ 388#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */
389#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ 389#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */
390#define NT_S390_TDB 0x308 /* s390 transaction diagnostic block */
390#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */ 391#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
391 392
392 393