diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2005-06-25 17:55:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-25 19:24:37 -0400 |
commit | 77fa22450de00d535de2cc8be653983560828000 (patch) | |
tree | 61644edb2263c3d0db3ea9e9518c6f76a60039e0 /include | |
parent | f901e5d1e06b3326c100c5d0df43656311befb81 (diff) |
[PATCH] s390: improved machine check handling
Improved machine check handling. Kernel is now able to receive machine checks
while in kernel mode (system call, interrupt and program check handling).
Also register validation is now performed.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-s390/lowcore.h | 7 | ||||
-rw-r--r-- | include/asm-s390/processor.h | 52 | ||||
-rw-r--r-- | include/asm-s390/ptrace.h | 2 | ||||
-rw-r--r-- | include/asm-s390/system.h | 21 | ||||
-rw-r--r-- | include/asm-s390/thread_info.h | 2 |
5 files changed, 44 insertions, 40 deletions
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h index df5172fc589d..76b5b19c0ae2 100644 --- a/include/asm-s390/lowcore.h +++ b/include/asm-s390/lowcore.h | |||
@@ -109,10 +109,14 @@ | |||
109 | 109 | ||
110 | #ifndef __s390x__ | 110 | #ifndef __s390x__ |
111 | #define __LC_PFAULT_INTPARM 0x080 | 111 | #define __LC_PFAULT_INTPARM 0x080 |
112 | #define __LC_CPU_TIMER_SAVE_AREA 0x0D8 | ||
112 | #define __LC_AREGS_SAVE_AREA 0x120 | 113 | #define __LC_AREGS_SAVE_AREA 0x120 |
114 | #define __LC_GPREGS_SAVE_AREA 0x180 | ||
113 | #define __LC_CREGS_SAVE_AREA 0x1C0 | 115 | #define __LC_CREGS_SAVE_AREA 0x1C0 |
114 | #else /* __s390x__ */ | 116 | #else /* __s390x__ */ |
115 | #define __LC_PFAULT_INTPARM 0x11B8 | 117 | #define __LC_PFAULT_INTPARM 0x11B8 |
118 | #define __LC_GPREGS_SAVE_AREA 0x1280 | ||
119 | #define __LC_CPU_TIMER_SAVE_AREA 0x1328 | ||
116 | #define __LC_AREGS_SAVE_AREA 0x1340 | 120 | #define __LC_AREGS_SAVE_AREA 0x1340 |
117 | #define __LC_CREGS_SAVE_AREA 0x1380 | 121 | #define __LC_CREGS_SAVE_AREA 0x1380 |
118 | #endif /* __s390x__ */ | 122 | #endif /* __s390x__ */ |
@@ -167,7 +171,8 @@ struct _lowcore | |||
167 | __u16 subchannel_nr; /* 0x0ba */ | 171 | __u16 subchannel_nr; /* 0x0ba */ |
168 | __u32 io_int_parm; /* 0x0bc */ | 172 | __u32 io_int_parm; /* 0x0bc */ |
169 | __u32 io_int_word; /* 0x0c0 */ | 173 | __u32 io_int_word; /* 0x0c0 */ |
170 | __u8 pad3[0xD8-0xC4]; /* 0x0c4 */ | 174 | __u8 pad3[0xD4-0xC4]; /* 0x0c4 */ |
175 | __u32 extended_save_area_addr; /* 0x0d4 */ | ||
171 | __u32 cpu_timer_save_area[2]; /* 0x0d8 */ | 176 | __u32 cpu_timer_save_area[2]; /* 0x0d8 */ |
172 | __u32 clock_comp_save_area[2]; /* 0x0e0 */ | 177 | __u32 clock_comp_save_area[2]; /* 0x0e0 */ |
173 | __u32 mcck_interruption_code[2]; /* 0x0e8 */ | 178 | __u32 mcck_interruption_code[2]; /* 0x0e8 */ |
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index fb46e9090b50..8bd14de69e35 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h | |||
@@ -207,6 +207,18 @@ unsigned long get_wchan(struct task_struct *p); | |||
207 | #endif /* __s390x__ */ | 207 | #endif /* __s390x__ */ |
208 | 208 | ||
209 | /* | 209 | /* |
210 | * Set PSW to specified value. | ||
211 | */ | ||
212 | static inline void __load_psw(psw_t psw) | ||
213 | { | ||
214 | #ifndef __s390x__ | ||
215 | asm volatile ("lpsw 0(%0)" : : "a" (&psw), "m" (psw) : "cc" ); | ||
216 | #else | ||
217 | asm volatile ("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" ); | ||
218 | #endif | ||
219 | } | ||
220 | |||
221 | /* | ||
210 | * Set PSW mask to specified value, while leaving the | 222 | * Set PSW mask to specified value, while leaving the |
211 | * PSW addr pointing to the next instruction. | 223 | * PSW addr pointing to the next instruction. |
212 | */ | 224 | */ |
@@ -214,8 +226,8 @@ unsigned long get_wchan(struct task_struct *p); | |||
214 | static inline void __load_psw_mask (unsigned long mask) | 226 | static inline void __load_psw_mask (unsigned long mask) |
215 | { | 227 | { |
216 | unsigned long addr; | 228 | unsigned long addr; |
217 | |||
218 | psw_t psw; | 229 | psw_t psw; |
230 | |||
219 | psw.mask = mask; | 231 | psw.mask = mask; |
220 | 232 | ||
221 | #ifndef __s390x__ | 233 | #ifndef __s390x__ |
@@ -241,30 +253,8 @@ static inline void __load_psw_mask (unsigned long mask) | |||
241 | */ | 253 | */ |
242 | static inline void enabled_wait(void) | 254 | static inline void enabled_wait(void) |
243 | { | 255 | { |
244 | unsigned long reg; | 256 | __load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT | |
245 | psw_t wait_psw; | 257 | PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY); |
246 | |||
247 | wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT | | ||
248 | PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY; | ||
249 | #ifndef __s390x__ | ||
250 | asm volatile ( | ||
251 | " basr %0,0\n" | ||
252 | "0: la %0,1f-0b(%0)\n" | ||
253 | " st %0,4(%1)\n" | ||
254 | " oi 4(%1),0x80\n" | ||
255 | " lpsw 0(%1)\n" | ||
256 | "1:" | ||
257 | : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw) | ||
258 | : "memory", "cc" ); | ||
259 | #else /* __s390x__ */ | ||
260 | asm volatile ( | ||
261 | " larl %0,0f\n" | ||
262 | " stg %0,8(%1)\n" | ||
263 | " lpswe 0(%1)\n" | ||
264 | "0:" | ||
265 | : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw) | ||
266 | : "memory", "cc" ); | ||
267 | #endif /* __s390x__ */ | ||
268 | } | 258 | } |
269 | 259 | ||
270 | /* | 260 | /* |
@@ -273,13 +263,11 @@ static inline void enabled_wait(void) | |||
273 | 263 | ||
274 | static inline void disabled_wait(unsigned long code) | 264 | static inline void disabled_wait(unsigned long code) |
275 | { | 265 | { |
276 | char psw_buffer[2*sizeof(psw_t)]; | ||
277 | unsigned long ctl_buf; | 266 | unsigned long ctl_buf; |
278 | psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1) | 267 | psw_t dw_psw; |
279 | & -sizeof(psw_t)); | ||
280 | 268 | ||
281 | dw_psw->mask = PSW_BASE_BITS | PSW_MASK_WAIT; | 269 | dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; |
282 | dw_psw->addr = code; | 270 | dw_psw.addr = code; |
283 | /* | 271 | /* |
284 | * Store status and then load disabled wait psw, | 272 | * Store status and then load disabled wait psw, |
285 | * the processor is dead afterwards | 273 | * the processor is dead afterwards |
@@ -301,7 +289,7 @@ static inline void disabled_wait(unsigned long code) | |||
301 | " oi 0x1c0,0x10\n" /* fake protection bit */ | 289 | " oi 0x1c0,0x10\n" /* fake protection bit */ |
302 | " lpsw 0(%1)" | 290 | " lpsw 0(%1)" |
303 | : "=m" (ctl_buf) | 291 | : "=m" (ctl_buf) |
304 | : "a" (dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" ); | 292 | : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" ); |
305 | #else /* __s390x__ */ | 293 | #else /* __s390x__ */ |
306 | asm volatile (" stctg 0,0,0(%2)\n" | 294 | asm volatile (" stctg 0,0,0(%2)\n" |
307 | " ni 4(%2),0xef\n" /* switch off protection */ | 295 | " ni 4(%2),0xef\n" /* switch off protection */ |
@@ -333,7 +321,7 @@ static inline void disabled_wait(unsigned long code) | |||
333 | " oi 0x384(1),0x10\n" /* fake protection bit */ | 321 | " oi 0x384(1),0x10\n" /* fake protection bit */ |
334 | " lpswe 0(%1)" | 322 | " lpswe 0(%1)" |
335 | : "=m" (ctl_buf) | 323 | : "=m" (ctl_buf) |
336 | : "a" (dw_psw), "a" (&ctl_buf), | 324 | : "a" (&dw_psw), "a" (&ctl_buf), |
337 | "m" (dw_psw) : "cc", "0", "1"); | 325 | "m" (dw_psw) : "cc", "0", "1"); |
338 | #endif /* __s390x__ */ | 326 | #endif /* __s390x__ */ |
339 | } | 327 | } |
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index 4eff8f2e3bf1..fc7c96edc697 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h | |||
@@ -276,7 +276,7 @@ typedef struct | |||
276 | #endif /* __s390x__ */ | 276 | #endif /* __s390x__ */ |
277 | 277 | ||
278 | #define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \ | 278 | #define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \ |
279 | PSW_DEFAULT_KEY) | 279 | PSW_MASK_MCHECK | PSW_DEFAULT_KEY) |
280 | #define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ | 280 | #define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \ |
281 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ | 281 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \ |
282 | PSW_MASK_PSTATE | PSW_DEFAULT_KEY) | 282 | PSW_MASK_PSTATE | PSW_DEFAULT_KEY) |
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index 81514d76edcf..e3cb3ce1d24a 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/types.h> | 16 | #include <asm/types.h> |
17 | #include <asm/ptrace.h> | 17 | #include <asm/ptrace.h> |
18 | #include <asm/setup.h> | 18 | #include <asm/setup.h> |
19 | #include <asm/processor.h> | ||
19 | 20 | ||
20 | #ifdef __KERNEL__ | 21 | #ifdef __KERNEL__ |
21 | 22 | ||
@@ -331,9 +332,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
331 | 332 | ||
332 | #ifdef __s390x__ | 333 | #ifdef __s390x__ |
333 | 334 | ||
334 | #define __load_psw(psw) \ | ||
335 | __asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" ); | ||
336 | |||
337 | #define __ctl_load(array, low, high) ({ \ | 335 | #define __ctl_load(array, low, high) ({ \ |
338 | typedef struct { char _[sizeof(array)]; } addrtype; \ | 336 | typedef struct { char _[sizeof(array)]; } addrtype; \ |
339 | __asm__ __volatile__ ( \ | 337 | __asm__ __volatile__ ( \ |
@@ -390,9 +388,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
390 | 388 | ||
391 | #else /* __s390x__ */ | 389 | #else /* __s390x__ */ |
392 | 390 | ||
393 | #define __load_psw(psw) \ | ||
394 | __asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" ); | ||
395 | |||
396 | #define __ctl_load(array, low, high) ({ \ | 391 | #define __ctl_load(array, low, high) ({ \ |
397 | typedef struct { char _[sizeof(array)]; } addrtype; \ | 392 | typedef struct { char _[sizeof(array)]; } addrtype; \ |
398 | __asm__ __volatile__ ( \ | 393 | __asm__ __volatile__ ( \ |
@@ -451,6 +446,20 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | |||
451 | /* For spinlocks etc */ | 446 | /* For spinlocks etc */ |
452 | #define local_irq_save(x) ((x) = local_irq_disable()) | 447 | #define local_irq_save(x) ((x) = local_irq_disable()) |
453 | 448 | ||
449 | /* | ||
450 | * Use to set psw mask except for the first byte which | ||
451 | * won't be changed by this function. | ||
452 | */ | ||
453 | static inline void | ||
454 | __set_psw_mask(unsigned long mask) | ||
455 | { | ||
456 | local_save_flags(mask); | ||
457 | __load_psw_mask(mask); | ||
458 | } | ||
459 | |||
460 | #define local_mcck_enable() __set_psw_mask(PSW_KERNEL_BITS) | ||
461 | #define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK) | ||
462 | |||
454 | #ifdef CONFIG_SMP | 463 | #ifdef CONFIG_SMP |
455 | 464 | ||
456 | extern void smp_ctl_set_bit(int cr, int bit); | 465 | extern void smp_ctl_set_bit(int cr, int bit); |
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h index fe101d41e849..6c18a3f24316 100644 --- a/include/asm-s390/thread_info.h +++ b/include/asm-s390/thread_info.h | |||
@@ -96,6 +96,7 @@ static inline struct thread_info *current_thread_info(void) | |||
96 | #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ | 96 | #define TIF_RESTART_SVC 4 /* restart svc with new svc number */ |
97 | #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ | 97 | #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ |
98 | #define TIF_SINGLE_STEP 6 /* deliver sigtrap on return to user */ | 98 | #define TIF_SINGLE_STEP 6 /* deliver sigtrap on return to user */ |
99 | #define TIF_MCCK_PENDING 7 /* machine check handling is pending */ | ||
99 | #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ | 100 | #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ |
100 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling | 101 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling |
101 | TIF_NEED_RESCHED */ | 102 | TIF_NEED_RESCHED */ |
@@ -109,6 +110,7 @@ static inline struct thread_info *current_thread_info(void) | |||
109 | #define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC) | 110 | #define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC) |
110 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) | 111 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) |
111 | #define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP) | 112 | #define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP) |
113 | #define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING) | ||
112 | #define _TIF_USEDFPU (1<<TIF_USEDFPU) | 114 | #define _TIF_USEDFPU (1<<TIF_USEDFPU) |
113 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | 115 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) |
114 | #define _TIF_31BIT (1<<TIF_31BIT) | 116 | #define _TIF_31BIT (1<<TIF_31BIT) |