aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-06 22:52:50 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-06 22:52:50 -0500
commitfe1b4ba400193176213f95be3ea711a53518a609 (patch)
treee60943d4703fca5a291fffc2e0b77a786b6db3f4 /arch
parentae5dd8e346efc25a5f9cc9d01bc0915c40eb38d9 (diff)
parent2470b648e17e0216922bb78c7f05b4668402459a (diff)
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6: [S390] cio: Call cancel_halt_clear even when actl == 0. [S390] cio: Use path verification to check for path state. [S390] cio: Fix locking when calling notify function. [S390] Fixed handling of access register mode faults. [S390] dasd: Use default recovery for SNSS requests [S390] check_bugs() should be inline. [S390] tape: Compression overwrites crypto setting [S390] nss: disable kexec. [S390] reipl: move dump_prefix_page out of text section. [S390] smp: disable preemption in smp_call_function/smp_call_function_on [S390] kprobes breaks BUG_ON
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/kernel/head31.S11
-rw-r--r--arch/s390/kernel/head64.S11
-rw-r--r--arch/s390/kernel/ipl.c4
-rw-r--r--arch/s390/kernel/kprobes.c21
-rw-r--r--arch/s390/kernel/machine_kexec.c5
-rw-r--r--arch/s390/kernel/reipl.S13
-rw-r--r--arch/s390/kernel/reipl64.S13
-rw-r--r--arch/s390/kernel/smp.c15
-rw-r--r--arch/s390/mm/fault.c105
10 files changed, 103 insertions, 97 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index d9425f59be91..0f293aa7b0fa 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -376,6 +376,8 @@ config SHARED_KERNEL
376 Select this option, if you want to share the text segment of the 376 Select this option, if you want to share the text segment of the
377 Linux kernel between different VM guests. This reduces memory 377 Linux kernel between different VM guests. This reduces memory
378 usage with lots of guests but greatly increases kernel size. 378 usage with lots of guests but greatly increases kernel size.
379 Also if a kernel was IPL'ed from a shared segment the kexec system
380 call will not work.
379 You should only select this option if you know what you are 381 You should only select this option if you know what you are
380 doing and want to exploit this feature. 382 doing and want to exploit this feature.
381 383
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index da7c8bb80982..dc364c1419af 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -121,7 +121,7 @@ startup_continue:
121 .long .Lduct # cr2: dispatchable unit control table 121 .long .Lduct # cr2: dispatchable unit control table
122 .long 0 # cr3: instruction authorization 122 .long 0 # cr3: instruction authorization
123 .long 0 # cr4: instruction authorization 123 .long 0 # cr4: instruction authorization
124 .long 0xffffffff # cr5: primary-aste origin 124 .long .Lduct # cr5: primary-aste origin
125 .long 0 # cr6: I/O interrupts 125 .long 0 # cr6: I/O interrupts
126 .long 0 # cr7: secondary space segment table 126 .long 0 # cr7: secondary space segment table
127 .long 0 # cr8: access registers translation 127 .long 0 # cr8: access registers translation
@@ -132,8 +132,6 @@ startup_continue:
132 .long 0 # cr13: home space segment table 132 .long 0 # cr13: home space segment table
133 .long 0xc0000000 # cr14: machine check handling off 133 .long 0xc0000000 # cr14: machine check handling off
134 .long 0 # cr15: linkage stack operations 134 .long 0 # cr15: linkage stack operations
135.Lduct: .long 0,0,0,0,0,0,0,0
136 .long 0,0,0,0,0,0,0,0
137.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu 135.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
138.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp 136.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
139.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg 137.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
@@ -147,6 +145,13 @@ startup_continue:
147.Linittu: .long init_thread_union 145.Linittu: .long init_thread_union
148.Lstartup_init: 146.Lstartup_init:
149 .long startup_init 147 .long startup_init
148 .align 64
149.Lduct: .long 0,0,0,0,.Lduald,0,0,0
150 .long 0,0,0,0,0,0,0,0
151 .align 128
152.Lduald:.rept 8
153 .long 0x80000000,0,0,0 # invalid access-list entries
154 .endr
150 155
151 .org 0x12000 156 .org 0x12000
152 .globl _ehead 157 .globl _ehead
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index af09e18cc5d0..37010709fe68 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -134,7 +134,7 @@ startup_continue:
134 .quad .Lduct # cr2: dispatchable unit control table 134 .quad .Lduct # cr2: dispatchable unit control table
135 .quad 0 # cr3: instruction authorization 135 .quad 0 # cr3: instruction authorization
136 .quad 0 # cr4: instruction authorization 136 .quad 0 # cr4: instruction authorization
137 .quad 0xffffffffffffffff # cr5: primary-aste origin 137 .quad .Lduct # cr5: primary-aste origin
138 .quad 0 # cr6: I/O interrupts 138 .quad 0 # cr6: I/O interrupts
139 .quad 0 # cr7: secondary space segment table 139 .quad 0 # cr7: secondary space segment table
140 .quad 0 # cr8: access registers translation 140 .quad 0 # cr8: access registers translation
@@ -145,14 +145,19 @@ startup_continue:
145 .quad 0 # cr13: home space segment table 145 .quad 0 # cr13: home space segment table
146 .quad 0xc0000000 # cr14: machine check handling off 146 .quad 0xc0000000 # cr14: machine check handling off
147 .quad 0 # cr15: linkage stack operations 147 .quad 0 # cr15: linkage stack operations
148.Lduct: .long 0,0,0,0,0,0,0,0
149 .long 0,0,0,0,0,0,0,0
150.Lpcmsk:.quad 0x0000000180000000 148.Lpcmsk:.quad 0x0000000180000000
151.L4malign:.quad 0xffffffffffc00000 149.L4malign:.quad 0xffffffffffc00000
152.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 150.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
153.Lnop: .long 0x07000700 151.Lnop: .long 0x07000700
154.Lparmaddr: 152.Lparmaddr:
155 .quad PARMAREA 153 .quad PARMAREA
154 .align 64
155.Lduct: .long 0,0,0,0,.Lduald,0,0,0
156 .long 0,0,0,0,0,0,0,0
157 .align 128
158.Lduald:.rept 8
159 .long 0x80000000,0,0,0 # invalid access-list entries
160 .endr
156 161
157 .org 0x12000 162 .org 0x12000
158 .globl _ehead 163 .globl _ehead
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 5a863a3bf10c..d125a4ead08d 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -1066,7 +1066,7 @@ static void do_reset_calls(void)
1066 reset->fn(); 1066 reset->fn();
1067} 1067}
1068 1068
1069extern __u32 dump_prefix_page; 1069u32 dump_prefix_page;
1070 1070
1071void s390_reset_system(void) 1071void s390_reset_system(void)
1072{ 1072{
@@ -1078,7 +1078,7 @@ void s390_reset_system(void)
1078 lc->panic_stack = S390_lowcore.panic_stack; 1078 lc->panic_stack = S390_lowcore.panic_stack;
1079 1079
1080 /* Save prefix page address for dump case */ 1080 /* Save prefix page address for dump case */
1081 dump_prefix_page = (unsigned long) lc; 1081 dump_prefix_page = (u32)(unsigned long) lc;
1082 1082
1083 /* Disable prefixing */ 1083 /* Disable prefixing */
1084 set_prefix(0); 1084 set_prefix(0);
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index a466bab6677e..8af549e95730 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -337,21 +337,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
337 } 337 }
338 338
339 p = get_kprobe(addr); 339 p = get_kprobe(addr);
340 if (!p) { 340 if (!p)
341 if (*addr != BREAKPOINT_INSTRUCTION) { 341 /*
342 /* 342 * No kprobe at this address. The fault has not been
343 * The breakpoint instruction was removed right 343 * caused by a kprobe breakpoint. The race of breakpoint
344 * after we hit it. Another cpu has removed 344 * vs. kprobe remove does not exist because on s390 we
345 * either a probepoint or a debugger breakpoint 345 * use stop_machine_run to arm/disarm the breakpoints.
346 * at this address. In either case, no further 346 */
347 * handling of this interrupt is appropriate.
348 *
349 */
350 ret = 1;
351 }
352 /* Not one of ours: let kernel handle it */
353 goto no_kprobe; 347 goto no_kprobe;
354 }
355 348
356 kcb->kprobe_status = KPROBE_HIT_ACTIVE; 349 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
357 set_current_kprobe(p, regs, kcb); 350 set_current_kprobe(p, regs, kcb);
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index 52f57af252b4..3c77dd36994c 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -19,6 +19,7 @@
19#include <asm/system.h> 19#include <asm/system.h>
20#include <asm/smp.h> 20#include <asm/smp.h>
21#include <asm/reset.h> 21#include <asm/reset.h>
22#include <asm/ipl.h>
22 23
23typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long); 24typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
24 25
@@ -29,6 +30,10 @@ int machine_kexec_prepare(struct kimage *image)
29{ 30{
30 void *reboot_code_buffer; 31 void *reboot_code_buffer;
31 32
33 /* Can't replace kernel image since it is read-only. */
34 if (ipl_flags & IPL_NSS_VALID)
35 return -ENOSYS;
36
32 /* We don't support anything but the default image type for now. */ 37 /* We don't support anything but the default image type for now. */
33 if (image->type != KEXEC_TYPE_DEFAULT) 38 if (image->type != KEXEC_TYPE_DEFAULT)
34 return -EINVAL; 39 return -EINVAL;
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index c3f4d9b95083..2f481cc3d1c9 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -8,6 +8,10 @@
8 8
9#include <asm/lowcore.h> 9#include <asm/lowcore.h>
10 10
11#
12# do_reipl_asm
13# Parameter: r2 = schid of reipl device
14#
11 .globl do_reipl_asm 15 .globl do_reipl_asm
12do_reipl_asm: basr %r13,0 16do_reipl_asm: basr %r13,0
13.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13) 17.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13)
@@ -16,12 +20,12 @@ do_reipl_asm: basr %r13,0
16 stm %r0,%r15,__LC_GPREGS_SAVE_AREA 20 stm %r0,%r15,__LC_GPREGS_SAVE_AREA
17 stctl %c0,%c15,__LC_CREGS_SAVE_AREA 21 stctl %c0,%c15,__LC_CREGS_SAVE_AREA
18 stam %a0,%a15,__LC_AREGS_SAVE_AREA 22 stam %a0,%a15,__LC_AREGS_SAVE_AREA
19 mvc __LC_PREFIX_SAVE_AREA(4),dump_prefix_page-.Lpg0(%r13) 23 l %r10,.Ldump_pfx-.Lpg0(%r13)
24 mvc __LC_PREFIX_SAVE_AREA(4),0(%r10)
20 stckc .Lclkcmp-.Lpg0(%r13) 25 stckc .Lclkcmp-.Lpg0(%r13)
21 mvc __LC_CLOCK_COMP_SAVE_AREA(8),.Lclkcmp-.Lpg0(%r13) 26 mvc __LC_CLOCK_COMP_SAVE_AREA(8),.Lclkcmp-.Lpg0(%r13)
22 stpt __LC_CPU_TIMER_SAVE_AREA 27 stpt __LC_CPU_TIMER_SAVE_AREA
23 st %r13, __LC_PSW_SAVE_AREA+4 28 st %r13, __LC_PSW_SAVE_AREA+4
24
25 lctl %c6,%c6,.Lall-.Lpg0(%r13) 29 lctl %c6,%c6,.Lall-.Lpg0(%r13)
26 lr %r1,%r2 30 lr %r1,%r2
27 mvc __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13) 31 mvc __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
@@ -55,6 +59,7 @@ do_reipl_asm: basr %r13,0
55 .align 8 59 .align 8
56.Lclkcmp: .quad 0x0000000000000000 60.Lclkcmp: .quad 0x0000000000000000
57.Lall: .long 0xff000000 61.Lall: .long 0xff000000
62.Ldump_pfx: .long dump_prefix_page
58 .align 8 63 .align 8
59.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1 64.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1
60.Lpcnew: .long 0x00080000,0x80000000+.Lecs 65.Lpcnew: .long 0x00080000,0x80000000+.Lecs
@@ -79,7 +84,3 @@ do_reipl_asm: basr %r13,0
79 .long 0x00000000,0x00000000 84 .long 0x00000000,0x00000000
80 .long 0x00000000,0x00000000 85 .long 0x00000000,0x00000000
81 .long 0x00000000,0x00000000 86 .long 0x00000000,0x00000000
82 .globl dump_prefix_page
83dump_prefix_page:
84 .long 0x00000000
85
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index dbb3eed38865..c41930499a5f 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -8,6 +8,12 @@
8 */ 8 */
9 9
10#include <asm/lowcore.h> 10#include <asm/lowcore.h>
11
12#
13# do_reipl_asm
14# Parameter: r2 = schid of reipl device
15#
16
11 .globl do_reipl_asm 17 .globl do_reipl_asm
12do_reipl_asm: basr %r13,0 18do_reipl_asm: basr %r13,0
13.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13) 19.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13)
@@ -20,7 +26,8 @@ do_reipl_asm: basr %r13,0
20 stg %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1) 26 stg %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1)
21 stctg %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1) 27 stctg %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1)
22 stam %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1) 28 stam %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1)
23 mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),dump_prefix_page-.Lpg0(%r13) 29 lg %r10,.Ldump_pfx-.Lpg0(%r13)
30 mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),0(%r10)
24 stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1) 31 stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1)
25 stckc .Lclkcmp-.Lpg0(%r13) 32 stckc .Lclkcmp-.Lpg0(%r13)
26 mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13) 33 mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13)
@@ -64,6 +71,7 @@ do_reipl_asm: basr %r13,0
64 .align 8 71 .align 8
65.Lclkcmp: .quad 0x0000000000000000 72.Lclkcmp: .quad 0x0000000000000000
66.Lall: .quad 0x00000000ff000000 73.Lall: .quad 0x00000000ff000000
74.Ldump_pfx: .quad dump_prefix_page
67.Lregsave: .quad 0x0000000000000000 75.Lregsave: .quad 0x0000000000000000
68 .align 16 76 .align 16
69/* 77/*
@@ -103,6 +111,3 @@ do_reipl_asm: basr %r13,0
103 .long 0x00000000,0x00000000 111 .long 0x00000000,0x00000000
104 .long 0x00000000,0x00000000 112 .long 0x00000000,0x00000000
105 .long 0x00000000,0x00000000 113 .long 0x00000000,0x00000000
106 .globl dump_prefix_page
107dump_prefix_page:
108 .long 0x00000000
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index ecaa432a99f8..97764f710bb7 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -94,10 +94,9 @@ static void __smp_call_function_map(void (*func) (void *info), void *info,
94 int cpu, local = 0; 94 int cpu, local = 0;
95 95
96 /* 96 /*
97 * Can deadlock when interrupts are disabled or if in wrong context, 97 * Can deadlock when interrupts are disabled or if in wrong context.
98 * caller must disable preemption
99 */ 98 */
100 WARN_ON(irqs_disabled() || in_irq() || preemptible()); 99 WARN_ON(irqs_disabled() || in_irq());
101 100
102 /* 101 /*
103 * Check for local function call. We have to have the same call order 102 * Check for local function call. We have to have the same call order
@@ -152,17 +151,18 @@ out:
152 * Run a function on all other CPUs. 151 * Run a function on all other CPUs.
153 * 152 *
154 * You must not call this function with disabled interrupts or from a 153 * You must not call this function with disabled interrupts or from a
155 * hardware interrupt handler. Must be called with preemption disabled. 154 * hardware interrupt handler. You may call it from a bottom half.
156 * You may call it from a bottom half.
157 */ 155 */
158int smp_call_function(void (*func) (void *info), void *info, int nonatomic, 156int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
159 int wait) 157 int wait)
160{ 158{
161 cpumask_t map; 159 cpumask_t map;
162 160
161 preempt_disable();
163 map = cpu_online_map; 162 map = cpu_online_map;
164 cpu_clear(smp_processor_id(), map); 163 cpu_clear(smp_processor_id(), map);
165 __smp_call_function_map(func, info, nonatomic, wait, map); 164 __smp_call_function_map(func, info, nonatomic, wait, map);
165 preempt_enable();
166 return 0; 166 return 0;
167} 167}
168EXPORT_SYMBOL(smp_call_function); 168EXPORT_SYMBOL(smp_call_function);
@@ -178,16 +178,17 @@ EXPORT_SYMBOL(smp_call_function);
178 * Run a function on one processor. 178 * Run a function on one processor.
179 * 179 *
180 * You must not call this function with disabled interrupts or from a 180 * You must not call this function with disabled interrupts or from a
181 * hardware interrupt handler. Must be called with preemption disabled. 181 * hardware interrupt handler. You may call it from a bottom half.
182 * You may call it from a bottom half.
183 */ 182 */
184int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic, 183int smp_call_function_on(void (*func) (void *info), void *info, int nonatomic,
185 int wait, int cpu) 184 int wait, int cpu)
186{ 185{
187 cpumask_t map = CPU_MASK_NONE; 186 cpumask_t map = CPU_MASK_NONE;
188 187
188 preempt_disable();
189 cpu_set(cpu, map); 189 cpu_set(cpu, map);
190 __smp_call_function_map(func, info, nonatomic, wait, map); 190 __smp_call_function_map(func, info, nonatomic, wait, map);
191 preempt_enable();
191 return 0; 192 return 0;
192} 193}
193EXPORT_SYMBOL(smp_call_function_on); 194EXPORT_SYMBOL(smp_call_function_on);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 641aef36ccc4..7462aebd3eb6 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -108,53 +108,40 @@ void bust_spinlocks(int yes)
108} 108}
109 109
110/* 110/*
111 * Check which address space is addressed by the access 111 * Returns the address space associated with the fault.
112 * register in S390_lowcore.exc_access_id. 112 * Returns 0 for kernel space, 1 for user space and
113 * Returns 1 for user space and 0 for kernel space. 113 * 2 for code execution in user space with noexec=on.
114 */ 114 */
115static int __check_access_register(struct pt_regs *regs, int error_code) 115static inline int check_space(struct task_struct *tsk)
116{
117 int areg = S390_lowcore.exc_access_id;
118
119 if (areg == 0)
120 /* Access via access register 0 -> kernel address */
121 return 0;
122 save_access_regs(current->thread.acrs);
123 if (regs && areg < NUM_ACRS && current->thread.acrs[areg] <= 1)
124 /*
125 * access register contains 0 -> kernel address,
126 * access register contains 1 -> user space address
127 */
128 return current->thread.acrs[areg];
129
130 /* Something unhealthy was done with the access registers... */
131 die("page fault via unknown access register", regs, error_code);
132 do_exit(SIGKILL);
133 return 0;
134}
135
136/*
137 * Check which address space the address belongs to.
138 * May return 1 or 2 for user space and 0 for kernel space.
139 * Returns 2 for user space in primary addressing mode with
140 * CONFIG_S390_EXEC_PROTECT on and kernel parameter noexec=on.
141 */
142static inline int check_user_space(struct pt_regs *regs, int error_code)
143{ 116{
144 /* 117 /*
145 * The lowest two bits of S390_lowcore.trans_exc_code indicate 118 * The lowest two bits of S390_lowcore.trans_exc_code
146 * which paging table was used: 119 * indicate which paging table was used.
147 * 0: Primary Segment Table Descriptor
148 * 1: STD determined via access register
149 * 2: Secondary Segment Table Descriptor
150 * 3: Home Segment Table Descriptor
151 */ 120 */
152 int descriptor = S390_lowcore.trans_exc_code & 3; 121 int desc = S390_lowcore.trans_exc_code & 3;
153 if (unlikely(descriptor == 1)) 122
154 return __check_access_register(regs, error_code); 123 if (desc == 3) /* Home Segment Table Descriptor */
155 if (descriptor == 2) 124 return switch_amode == 0;
156 return current->thread.mm_segment.ar4; 125 if (desc == 2) /* Secondary Segment Table Descriptor */
157 return ((descriptor != 0) ^ (switch_amode)) << s390_noexec; 126 return tsk->thread.mm_segment.ar4;
127#ifdef CONFIG_S390_SWITCH_AMODE
128 if (unlikely(desc == 1)) { /* STD determined via access register */
129 /* %a0 always indicates primary space. */
130 if (S390_lowcore.exc_access_id != 0) {
131 save_access_regs(tsk->thread.acrs);
132 /*
133 * An alet of 0 indicates primary space.
134 * An alet of 1 indicates secondary space.
135 * Any other alet values generate an
136 * alen-translation exception.
137 */
138 if (tsk->thread.acrs[S390_lowcore.exc_access_id])
139 return tsk->thread.mm_segment.ar4;
140 }
141 }
142#endif
143 /* Primary Segment Table Descriptor */
144 return switch_amode << s390_noexec;
158} 145}
159 146
160/* 147/*
@@ -265,16 +252,16 @@ out_fault:
265 * 11 Page translation -> Not present (nullification) 252 * 11 Page translation -> Not present (nullification)
266 * 3b Region third trans. -> Not present (nullification) 253 * 3b Region third trans. -> Not present (nullification)
267 */ 254 */
268static inline void __kprobes 255static inline void
269do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) 256do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
270{ 257{
271 struct task_struct *tsk; 258 struct task_struct *tsk;
272 struct mm_struct *mm; 259 struct mm_struct *mm;
273 struct vm_area_struct * vma; 260 struct vm_area_struct * vma;
274 unsigned long address; 261 unsigned long address;
275 int user_address;
276 const struct exception_table_entry *fixup; 262 const struct exception_table_entry *fixup;
277 int si_code = SEGV_MAPERR; 263 int si_code;
264 int space;
278 265
279 tsk = current; 266 tsk = current;
280 mm = tsk->mm; 267 mm = tsk->mm;
@@ -294,7 +281,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
294 NULL pointer write access in kernel mode. */ 281 NULL pointer write access in kernel mode. */
295 if (!(regs->psw.mask & PSW_MASK_PSTATE)) { 282 if (!(regs->psw.mask & PSW_MASK_PSTATE)) {
296 address = 0; 283 address = 0;
297 user_address = 0; 284 space = 0;
298 goto no_context; 285 goto no_context;
299 } 286 }
300 287
@@ -309,15 +296,15 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
309 * the address 296 * the address
310 */ 297 */
311 address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK; 298 address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
312 user_address = check_user_space(regs, error_code); 299 space = check_space(tsk);
313 300
314 /* 301 /*
315 * Verify that the fault happened in user space, that 302 * Verify that the fault happened in user space, that
316 * we are not in an interrupt and that there is a 303 * we are not in an interrupt and that there is a
317 * user context. 304 * user context.
318 */ 305 */
319 if (user_address == 0 || in_atomic() || !mm) 306 if (unlikely(space == 0 || in_atomic() || !mm))
320 goto no_context; 307 goto no_context;
321 308
322 /* 309 /*
323 * When we get here, the fault happened in the current 310 * When we get here, the fault happened in the current
@@ -328,12 +315,13 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
328 315
329 down_read(&mm->mmap_sem); 316 down_read(&mm->mmap_sem);
330 317
331 vma = find_vma(mm, address); 318 si_code = SEGV_MAPERR;
332 if (!vma) 319 vma = find_vma(mm, address);
333 goto bad_area; 320 if (!vma)
321 goto bad_area;
334 322
335#ifdef CONFIG_S390_EXEC_PROTECT 323#ifdef CONFIG_S390_EXEC_PROTECT
336 if (unlikely((user_address == 2) && !(vma->vm_flags & VM_EXEC))) 324 if (unlikely((space == 2) && !(vma->vm_flags & VM_EXEC)))
337 if (!signal_return(mm, regs, address, error_code)) 325 if (!signal_return(mm, regs, address, error_code))
338 /* 326 /*
339 * signal_return() has done an up_read(&mm->mmap_sem) 327 * signal_return() has done an up_read(&mm->mmap_sem)
@@ -389,7 +377,7 @@ survive:
389 * The instruction that caused the program check will 377 * The instruction that caused the program check will
390 * be repeated. Don't signal single step via SIGTRAP. 378 * be repeated. Don't signal single step via SIGTRAP.
391 */ 379 */
392 clear_tsk_thread_flag(current, TIF_SINGLE_STEP); 380 clear_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
393 return; 381 return;
394 382
395/* 383/*
@@ -419,7 +407,7 @@ no_context:
419 * Oops. The kernel tried to access some bad page. We'll have to 407 * Oops. The kernel tried to access some bad page. We'll have to
420 * terminate things with extreme prejudice. 408 * terminate things with extreme prejudice.
421 */ 409 */
422 if (user_address == 0) 410 if (space == 0)
423 printk(KERN_ALERT "Unable to handle kernel pointer dereference" 411 printk(KERN_ALERT "Unable to handle kernel pointer dereference"
424 " at virtual kernel address %p\n", (void *)address); 412 " at virtual kernel address %p\n", (void *)address);
425 else 413 else
@@ -462,13 +450,14 @@ do_sigbus:
462 goto no_context; 450 goto no_context;
463} 451}
464 452
465void do_protection_exception(struct pt_regs *regs, unsigned long error_code) 453void __kprobes do_protection_exception(struct pt_regs *regs,
454 unsigned long error_code)
466{ 455{
467 regs->psw.addr -= (error_code >> 16); 456 regs->psw.addr -= (error_code >> 16);
468 do_exception(regs, 4, 1); 457 do_exception(regs, 4, 1);
469} 458}
470 459
471void do_dat_exception(struct pt_regs *regs, unsigned long error_code) 460void __kprobes do_dat_exception(struct pt_regs *regs, unsigned long error_code)
472{ 461{
473 do_exception(regs, error_code & 0xff, 0); 462 do_exception(regs, error_code & 0xff, 0);
474} 463}